'Android listview content won't refresh upon call back
I got some problem when trying to refresh the list view content on call back. Inside my onCreate():
private ListAdapter mAdapter;
private ListView listview;
mAdapter = new ListAdapter(getActivity());
listview.setAdapter(mAdapter);
Then, inside my callback which is working as I managed to print out the data:
public void callback(ArrayList<Transaction> list)
{
expenseslist.clear();
Log.d("SIZE", String.valueOf(list.size()));
for(int i = 0; i < list.size(); i++){
expenseslist.add(list.get(i));
}
mAdapter.notifyDataSetChanged();
listview.invalidateViews();
}
private class ListAdapter extends BaseAdapter {
LayoutInflater inflater;
ViewHolder viewHolder;
public ListAdapter(Context context) {
inflater = LayoutInflater.from(context);
}
public int getCount() {
return expenseslist.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.transactioncat_listview_row,
null);
viewHolder = new ViewHolder();
viewHolder.txt_dcatTitle = (TextView) convertView
.findViewById(R.id.txtCatTitle);
viewHolder.txt_dcatTotal = (TextView) convertView
.findViewById(R.id.txtCatTotal);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.txt_dcatTitle.setText(expenseslist.get(position)
.getCategory().getCategoryName().trim());
viewHolder.txt_dcatTotal.setText(Extra.formatCurrency(expenseslist.get(position)
.getTransactionAmt()));
return convertView;
}
}
I called the notifyDataSetChanged() and invalidateViews() but it is not refreshing. I am not adding new rows to the list view but rather, updating the content in each row.
How can I do this correctly?
public class ExpenseActivity extends Fragment implements TransactionListCallBack{
private ArrayList<Transaction> transactionlist = new ArrayList<Transaction>();
private ArrayList<Transaction> expenseslist = new ArrayList<Transaction>();
private ListAdapter mAdapter;
private ListView listview;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_expense,container,false);
expenseslist.clear();
transactionlist = (ArrayList<Transaction>)getArguments().getSerializable("transactionlist");
for(int j = 0; j < transactionlist.size(); j++){
expenseslist.add(transactionlist.get(j));
}
listview = (ListView) v.findViewById(R.id.transactionCatListview);
// Binding the list into list view
mAdapter = new ListAdapter(getActivity());
listview.setAdapter(mAdapter);
return v;
}
@Override
public void callback(ArrayList<Transaction> list)
{
total = 0;
expenseslist.clear();
for(int i = 0; i < list.size(); i++){
expenseslist.add(list.get(i));
}
}
mAdapter.notifyDataSetChanged();
listview.invalidateViews();
}
private class ListAdapter extends BaseAdapter {
LayoutInflater inflater;
ViewHolder viewHolder;
public ListAdapter(Context context) {
inflater = LayoutInflater.from(context);
}
public int getCount() {
return expenseslist.size();
}
public Object getItem(int position) {
return expenseslist.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.transactioncat_listview_row,
null);
viewHolder = new ViewHolder();
viewHolder.txt_dcatTitle = (TextView) convertView
.findViewById(R.id.txtCatTitle);
viewHolder.txt_dcatTotal = (TextView) convertView
.findViewById(R.id.txtCatTotal);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.txt_dcatTitle.setText(expenseslist.get(position)
.getCategory().getCategoryName().trim());
viewHolder.txt_dcatTotal.setText(Extra.formatCurrency(expenseslist.get(position)
.getTransactionAmt()));
return convertView;
}
}
private class ViewHolder {
CircularProgressBar progressBar;
ImageView background_catview;
ImageView icon_catview;
TextView txt_dcatTitle;
TextView txt_dcatTotal;
}
// override menu item to add new transaction
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.menu_main_addtransaction, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_openNewTransaction) {
new GetAllCategoriesAsyncTask(
new GetAllCategoriesAsyncTask.OnRoutineFinished() {
public void onFinish() {
AddTransactionActivity addFragment = new AddTransactionActivity();
FragmentTransaction tt = getFragmentManager().beginTransaction();
addFragment.setTransactionListCallBack(ExpenseActivity.this);
tt.replace(R.id.frame,addFragment);
tt.addToBackStack("tag");
tt.commit();
}
}).execute();
}
return super.onOptionsItemSelected(item);
}
}
Solution 1:[1]
Make this change
public Object getItem(int position) {
return expenseslist.get(position);
}
Solution 2:[2]
You need to keep a list of your data in adapter for notifyDataSetChanged to work:
Change
mAdapter = new ListAdapter(getActivity(), expenseslist);
And inside your adapter:
list<Transaction> expenseslist;
public ListAdapter(Context context, list<Transaction> expenseslist) {
inflater = LayoutInflater.from(context);
this.expenseslist = expenseslist;
}
EDIT:
Also change these methods:
public Transaction getItem(int position) {
return expenseslist.get(position);
}
public long getItemId(int position) {
return expenseslist.get(position).getId();
}
Solution 3:[3]
Hi Denise in your adapter create a new function called updateTransactions(). This is the code for function where expenseslist is the list your passing to adapter.
public void updateTransactions(List<Transaction> list) {
expenseslist.clear();
expenseslist.addAll(list);
notifyDataSetChanged();
Log.d("SIZE", String.valueOf(expensesList.size()));
}
Then in your callback function call updateTransactions() using instance of adapter like this
public void callback(ArrayList<Transaction> list)
{
mAdapter.updateTransactions(list);
}
Edit: Demo run code
package ********;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
/**
* Created by Rishabh Bhatia on 18/5/17.
*/
public class TestActivity extends Activity {
private ListView list;
private ListAdapter adapter;
private ArrayList<String> dataList;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
list = (ListView) findViewById(R.id.list);
dataList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
String string = "abc";
dataList.add(string);
}
adapter = new ListAdapter(this, dataList);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d("rishabh", "something is selected");
String transaction = dataList.get(0);
transaction = "xyz";
dataList.remove(0);
dataList.add(0, transaction);
adapter.updateExpenses(dataList);
}
});
}
private class ListAdapter extends BaseAdapter {
private ArrayList<String> expenseslist;
LayoutInflater inflater;
ViewHolder viewHolder;
public ListAdapter(Context context, ArrayList<String> list) {
inflater = LayoutInflater.from(context);
this.expenseslist = (ArrayList<String>) list.clone();
}
public int getCount() {
return expenseslist.size();
}
public Object getItem(int position) {
return expenseslist.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.row,
null);
viewHolder = new ViewHolder();
viewHolder.text = (TextView) convertView
.findViewById(R.id.tvRow);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.text.setText(expenseslist.get(position));
return convertView;
}
public void updateExpenses(ArrayList<String> list) {
Log.d("rishabh", "updating the expenses "+list.size());
expenseslist.clear();
for(int i =0; i<list.size(); i++) {
Log.d("rishabh", "inside for loop");
expenseslist.add(list.get(i));
Log.d("rishabh", "updating item to list "+list.get(i));
}
notifyDataSetChanged();
Log.d("rishabh", "updating the expenses "+expenseslist.size());
}
}
static class ViewHolder {
private TextView text;
}
}
Hopefully it helps.
Solution 4:[4]
Are you are coding within a fragment? Could i ask where/when you call this method
public void callback(ArrayList list);
As I guess you call this method from an activity on a lifecycle method right after you add the fragment. Or maybe you call this method not in a UI thread with a try - catch block.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dishonered |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | SangLe |
