Programming

notifyDataSetChanged 후에 Android ListView가 새로 고쳐지지 않습니다

procodes 2020. 7. 26. 14:03
반응형

notifyDataSetChanged 후에 Android ListView가 새로 고쳐지지 않습니다


내 ListFragment 코드

public class ItemFragment extends ListFragment {

    private DatabaseHandler dbHelper;
    private static final String TITLE = "Items";
    private static final String LOG_TAG = "debugger";
    private ItemAdapter adapter;
    private List<Item> items;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.item_fragment_list, container, false);        
        return view;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.setHasOptionsMenu(true);
        super.onCreate(savedInstanceState);
        getActivity().setTitle(TITLE);
        dbHelper = new DatabaseHandler(getActivity());
        items = dbHelper.getItems(); 
        adapter = new ItemAdapter(getActivity().getApplicationContext(), items);
        this.setListAdapter(adapter);

    }



    @Override
    public void onResume() {
        super.onResume();
        items.clear();
        items = dbHelper.getItems(); //reload the items from database
        adapter.notifyDataSetChanged();
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        if(dbHelper != null) { //item is edited
            Item item = (Item) this.getListAdapter().getItem(position);
            Intent intent = new Intent(getActivity(), AddItemActivity.class);
            intent.putExtra(IntentConstants.ITEM, item);
            startActivity(intent);
        }
    }
}

내 목록보기

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

그러나 이것은 새로 고침되지 않습니다 ListView. 앱을 다시 시작한 후에도 업데이트 된 항목이 표시되지 않습니다. ItemAdapter확장BaseAdapter

public class ItemAdapter extends BaseAdapter{

    private LayoutInflater inflater;
    private List<Item> items;
    private Context context;

    public ProjectListItemAdapter(Context context, List<Item> items) {
        super();
        inflater = LayoutInflater.from(context);
        this.context = context;
        this.items = items;

    }

    @Override
    public int getCount() {
        return items.size();
    }

    @Override
    public Object getItem(int position) {
        return items.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ItemViewHolder holder = null;
        if(convertView == null) {
            holder = new ItemViewHolder();
            convertView = inflater.inflate(R.layout.list_item, parent,false);
            holder.itemName = (TextView) convertView.findViewById(R.id.topText);
            holder.itemLocation = (TextView) convertView.findViewById(R.id.bottomText);
            convertView.setTag(holder);
        } else {
            holder = (ItemViewHolder) convertView.getTag();
        }
        holder.itemName.setText("Name: " + items.get(position).getName());
        holder.itemLocation.setText("Location: " + items.get(position).getLocation());
        if(position % 2 == 0) {                                                                                 
            convertView.setBackgroundColor(context.getResources().getColor(R.color.evenRowColor));
        } else {    
            convertView.setBackgroundColor(context.getResources().getColor(R.color.oddRowColor));
        }
        return convertView;
    }

    private static class ItemViewHolder {
        TextView itemName;
        TextView itemLocation;
    }
}

누군가 도와주세요?


에서 onResume방법을 살펴보십시오 ItemFragment.

@Override
public void onResume() {
    super.onResume();
    items.clear();
    items = dbHelper.getItems(); // reload the items from database
    adapter.notifyDataSetChanged();
}

호출하기 전에 방금 업데이트 한 notifyDataSetChanged()것은 어댑터의 필드가 private List<Item> items;아니라 조각의 동일하게 선언 된 필드입니다. 어댑터는 여전히 어댑터를 만들 때 전달한 항목 목록에 대한 참조를 저장합니다 (예 : 조각의 onCreate). 가장 짧은 (변경 횟수를 고려할 때) 코드를 예상대로 우아하게 만들 수없는 방법은 단순히 줄을 바꾸는 것입니다.

    items = dbHelper.getItems(); // reload the items from database

    items.addAll(dbHelper.getItems()); // reload the items from database

보다 우아한 솔루션 :

1) 항목 private List<Item> items;제거하십시오 ItemFragment-어댑터에서만 참조해야합니다.

2) onCreate를 다음으로 변경하십시오.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.setHasOptionsMenu(true);
    getActivity().setTitle(TITLE);
    dbHelper = new DatabaseHandler(getActivity());
    adapter = new ItemAdapter(getActivity(), dbHelper.getItems());
    setListAdapter(adapter);
}

3) ItemAdapter에 메소드를 추가하십시오.

public void swapItems(List<Item> items) {
    this.items = items;
    notifyDataSetChanged();
}

4) onResume을 다음으로 변경하십시오.

@Override
public void onResume() {
    super.onResume();
    adapter.swapItems(dbHelper.getItems());
}

에서 다시로드 된 항목을 전역 변수 항목에 할당 onResume()하지만 ItemAdapter'items'라는 자체 인스턴스 변수가 있으므로 클래스에 반영되지 않습니다 .

상쾌한를 들어 ListView,에서 새로 고침 ()를 추가 ItemAdapter목록 데이터 즉, 항목을 허용 클래스

class ItemAdapter
{
    .....

    public void refresh(List<Item> items)
    {
        this.items = items;
        notifyDataSetChanged();
    } 
}

onResume()다음 코드로 업데이트

@Override
public void onResume()
{
    super.onResume();
    items.clear();
    items = dbHelper.getItems(); //reload the items from database
    **adapter.refresh(items);**
}

onResume () 에서이 줄을 변경하십시오.

items = dbHelper.getItems(); //reload the items from database

items.addAll(dbHelper.getItems()); //reload the items from database

The problem is that you're never telling your adapter about the new items list. If you don't want to pass a new list to your adapter (as it seems you don't), then just use items.addAll after your clear(). This will ensure you are modifying the same list that the adapter has a reference to.


If the adapter is already set, setting it again will not refresh the listview. Instead first check if the listview has a adapter and then call the appropriate method.

I think its not a very good idea to create a new instance of the adapter while setting the list view. Instead, create an object.

BuildingAdapter adapter = new BuildingAdapter(context);

    if(getListView().getAdapter() == null){ //Adapter not set yet.
     setListAdapter(adapter);
    }
    else{ //Already has an adapter
    adapter.notifyDataSetChanged();
    }

Also you might try to run the refresh list on UI Thread:

activity.runOnUiThread(new Runnable() {         
        public void run() {
              //do your modifications here

              // for example    
              adapter.add(new Object());
              adapter.notifyDataSetChanged()  
        }
});

If you want to update your listview doesn't matter if you want to do that on onResume(), onCreate() or in some other function, first thing that you have to realize is that you won't need to create a new instance of the adapter, just populate the arrays with your data again. The idea is something similar to this :

private ArrayList<String> titles;
private MyListAdapter adapter;
private ListView myListView;

@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    myListView = (ListView) findViewById(R.id.my_list);

    titles = new ArrayList<String>()

    for(int i =0; i<20;i++){
        titles.add("Title "+i);
    }

    adapter = new MyListAdapter(this, titles);
    myListView.setAdapter(adapter);
}


@Override
public void onResume(){
    super.onResume();
    // first clear the items and populate the new items
    titles.clear();
    for(int i =0; i<20;i++){
        titles.add("New Title "+i);
    }
    adapter.notifySetDataChanged();
}

So depending on that answer you should use the same List<Item> in your Fragment. In your first adapter initialization you fill your list with the items and set adapter to your listview. After that in every change in your items you have to clear the values from the main List<Item> items and than populate it again with your new items and call notifySetDataChanged();.

That's how it works : ).


An answer from AlexGo did the trick for me:

getActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
         messages.add(m);
         adapter.notifyDataSetChanged();
         getListView().setSelection(messages.size()-1);
        }
});

List Update worked for me before when the update was triggered from a GUI event, thus being in the UI thread.

However, when I update the list from another event/thread - i.e. a call from outside the app, the update would not be in the UI thread and it ignored the call to getListView. Calling the update with runOnUiThread as above did the trick for me. Thanks!!


Try this

@Override
public void onResume() {
super.onResume();
items.clear();
items = dbHelper.getItems(); //reload the items from database
adapter = new ItemAdapter(getActivity(), items);//reload the items from database
adapter.notifyDataSetChanged();
}

adpter.notifyDataSetInvalidated();

Try this in onPause() method of Activity class.


adapter.setNotifyDataChanged()

should do the trick.


Try like this:

this.notifyDataSetChanged();

instead of:

adapter.notifyDataSetChanged();

You have to notifyDataSetChanged() to the ListView not to the adapter class.


If your list is contained in the Adapter itself, calling the function that updates the list should also call notifyDataSetChanged().

Running this function from the UI Thread did the trick for me:

The refresh() function inside the Adapter

public void refresh(){
    //manipulate list
    notifyDataSetChanged();
}

Then in turn run this function from the UI Thread

getActivity().runOnUiThread(new Runnable() { 
    @Override
    public void run() {
          adapter.refresh()  
    }
});

참고URL : https://stackoverflow.com/questions/14503006/android-listview-not-refreshing-after-notifydatasetchanged

반응형