सूचना सूची के बाद Android ListView ताज़ा नहीं है


116

मेरा 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;
    }
}

क्या कोई कृपया मदद कर सकता है?


2
क्या आपने यह देखने के लिए परीक्षण किया है कि क्या डेटाबेस ऑपरेशन ठीक से काम कर रहा है? एडेप्टर कैसा दिखता है? इसके अलावा, यदि आप adapterसंदर्भ के लिए एक ऑब्जेक्ट बनाते हैं तो आप इसे नीचे की एक पंक्ति के लिए क्यों परीक्षण करते हैं?
लुक्सप्रोग

कोड अपवाद नहीं फेंकता है और मैंने डीबग का उपयोग करके जाँच की है। त्रुटि के बिना निष्पादित सभी तरीके। हाँ एक मूर्खतापूर्ण गलती है।
कोडर

जवाबों:


229

इनकी 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;बल्कि टुकड़े के समान रूप से घोषित क्षेत्र है। एडेप्टर तब भी आपके द्वारा पास किए गए आइटमों की सूची के संदर्भ में संग्रहीत करता है जब आपने एडॉप्टर बनाया था (उदाहरण के लिए अंश का ऑनक्रिएट)। सबसे छोटा (परिवर्तनों की संख्या के संदर्भ में) लेकिन अपने कोड को व्यवहार करने का सुरुचिपूर्ण तरीका नहीं है जैसा कि आप उम्मीद करते हैं कि बस लाइन को बदलना है:

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

साथ में

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

एक और अधिक सुंदर समाधान:

1) आइटम private List<Item> items;को हटा दें ItemFragment- हमें केवल एडाप्टर में उनके लिए संदर्भ रखने की आवश्यकता है

2) परिवर्तन पर बनाएँ:

@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) विधि जोड़ें:

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

4) अपने onResume को इसमें बदलें:

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

क्या एडॉप्टर में पूरी dbHelper चीज़ को स्थानांतरित करना क्लीनर नहीं होगा? तो आप केवल कॉल करेंगे adapter.swapItems();और एडॉप्टर dbHelper.getItems()सामान करेंगे। लेकिन वैसे भी उत्तर के लिए धन्यवाद :)
अंसार

7
आपको आइटम क्यों साफ़ करना चाहिए () और आइटम को फिर से जोड़ना चाहिए? क्या इसका उद्देश्य ठीक नहीं है notifyDataSetChanged()?
फिल रयान

1
@tomsaz क्या आप इस stackoverflow.com/questions/28148618/… पर

1
धन्यवाद @tomsaz Gawel, आपका स्वप्नदोष वास्तव में मुझे बहुत मदद करता है, मुझे नहीं पता कि मेरा एडॉप्टर क्यों नहीं है। नोटिफाइडसेटैगिंग काम नहीं करता है, क्योंकि "लिस्ट" जो मैं पास कर रहा हूं, वह भी अपडेट है, यहां तक ​​कि मैंने इसे प्रिंटिंग लॉग से चेक किया है, क्या आप मुझे यह समझा सकते हैं अवधारणा
किम्मी ढींगरा

1
यह उत्तर सही है। समस्या यह है कि ADAPTER का आइटम ArrayList अपडेट नहीं किया जा रहा था। इसका मतलब है कि आप बिना किसी प्रभाव के जब तक आपका चेहरा नीला नहीं हो जाता है, तब तक आप नोटाडसेटेकचेंज कर सकते हैं। एडेप्टर आपके डेटासेट को उसी डेटासेट के साथ अपडेट कर रहा है ताकि कोई परिवर्तन न हो। इस उत्तर में पोस्ट किए गए समाधान का एक और विकल्प जो क्लीनर हो सकता है: एडेप्टर.मिट्स = आइटम; adapter.notifyDataSetChanged ();
रे ली

23

आप वैश्विक वैरिएबल आइटम में पुनः लोड किए गए आइटम असाइन कर रहे हैं onResume(), लेकिन यह ItemAdapterकक्षा में प्रतिबिंबित नहीं होगा , क्योंकि इसका अपना इंस्टा वेरिएबल है जिसे 'आइटम' कहा जाता है।

रिफ्रेशिंग के लिए 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);**
}

1
यह बिल्कुल सही है। एडेप्टर का निर्माता वस्तुओं के पारित होने की उम्मीद करता है, लेकिन वह केवल बाहरी वर्ग के क्षेत्र को अपडेट करता है।
लग्जरी मॉम

हाय संतोष। क्या आप इसी तरह की समस्या पर एक नज़र डाल सकते हैं: stackoverflow.com/questions/35850715/…

8

OnResume () में इस लाइन को बदलें

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

सेवा

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

समस्या यह है कि आप अपने एडॉप्टर को नई आइटम सूची के बारे में कभी नहीं बता रहे हैं। यदि आप अपने एडॉप्टर को नई सूची नहीं देना चाहते हैं (जैसा कि ऐसा लगता है कि आप नहीं हैं), तो बस items.addAllअपने बाद का उपयोग करें clear()। यह सुनिश्चित करेगा कि आप उसी सूची को संशोधित कर रहे हैं जिसके लिए एडेप्टर का संदर्भ है।


यह भ्रामक है कि adapter.clear()एडेप्टर को यह महसूस करने के लिए मजबूर नहीं करता है कि दृश्य ताज़ा होना चाहिए, लेकिन adapter.add()या adapter.addAll()करता है। जवाब के लिए धन्यवाद!
w3bshark

ध्यान दें कि मैं items.addAll()एडेप्टर का उपयोग कर रहा था और एडेप्टर नहीं। केवल एक चीज जो एडेप्टर को परिवर्तनों पर प्रतिक्रिया दे रही है वह है notifyDataSetChanged। एडेप्टर सभी में परिवर्तन देखता है इसका कारण यह है कि एडेप्टर itemsउसी सूची का उपयोग करता है।
जस्टिन ब्रेइटफेलर

4

यदि एडेप्टर पहले से सेट है, तो इसे फिर से सेट करने से लिस्टव्यू रिफ्रेश नहीं होगा। इसके बजाय पहले जांच लें कि सूची में एडॉप्टर है या नहीं और फिर उपयुक्त विधि को कॉल करें।

मुझे लगता है कि सूची को स्थापित करते समय एडेप्टर का एक नया उदाहरण बनाने के लिए इसका बहुत अच्छा विचार नहीं है। इसके बजाय, एक वस्तु बनाएँ।

BuildingAdapter adapter = new BuildingAdapter(context);

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

इसके अलावा आप UI थ्रेड पर रिफ्रेश लिस्ट चलाने की कोशिश कर सकते हैं:

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

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

मुझे यकीन नहीं है कि यूआई धागा कैसे लागू किया जाए। मेरी मुख्य गतिविधि में 3 टुकड़े (टैब) हैं और प्रश्न में कोड उस टुकड़े से संबंधित है जिसमें सूची दृश्य है। आइटम पास करने का कारण ItemAdapterक्या मैं पंक्तियों को रंगना चाहता हूं और सूची दृश्य कई डेटा आइटम प्रदर्शित करता है। मैंने एडॉप्टर के लिए कोड पोस्ट किया है।
कोडर

आपको अपना कोड डालना होगा जो "उदाहरण" का उपयोग करके मेरी सूची में आपकी सूची को पॉप्युलेट करता है। "गतिविधि" के बजाय
एलेक्सगॉ

कुछ मामलों में जब आप विभिन्न थ्रेड में InformDataSetChanged () चलाते हैं, तो यह अपडेट नहीं किया जाता है, इसलिए उपरोक्त समाधान कुछ मामलों के लिए सही है।
अयमान अल-अबी

4

यदि आप अपनी सूची को अपडेट करना चाहते हैं, तो इससे कोई फर्क नहीं पड़ता कि आप ऐसा करना चाहते हैं onResume(), onCreate()या किसी अन्य फ़ंक्शन में, पहली बात यह है कि आपको यह महसूस करना होगा कि आपको एडॉप्टर का एक नया उदाहरण बनाने की आवश्यकता नहीं होगी, बस आबाद करें आपके डेटा के साथ फिर से सरणियाँ। विचार कुछ इस तरह है:

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();
}

तो उस जवाब के आधार पर आपको List<Item>अपने में इसका उपयोग करना चाहिए Fragment। अपने पहले अडैप्टर इनिशियलाइज़ेशन में आप अपनी सूची को आइटम्स के साथ भरते हैं और एडॉप्टर को अपनी सूची में सेट करते हैं। उसके बाद अपने आइटम में हर परिवर्तन में आपको मुख्य से मूल्यों को साफ़ करना होगा List<Item> itemsऔर इसे अपनी नई वस्तुओं और कॉल के साथ फिर से आबाद करना होगा notifySetDataChanged();

यह वैसे काम करता है : )।


उत्तर के लिए धन्यवाद। मैंने आपके द्वारा बताए गए परिवर्तनों को किया। मैंने अपना कोड पोस्ट कर दिया है। यह अभी भी काम नहीं करता है। अब नया आइटम जोड़ने पर यह सूची दृश्य भी प्रदर्शित नहीं करता है।
कोडर

मैंने कोड बदल दिया है। निरीक्षण करने के लिए अजीब बात यह है कि आइटम डीबी में अद्यतन नहीं हो रहा है
कोडर

यह थ्रेड डेटाबेस stackoverflow.com/questions/14555332/… के लिए है
Coder

3

AlexGo के एक जवाब ने मेरे लिए किया मुश्किल:

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

जब GUI घटना से अपडेट शुरू हो गया था, तो इस प्रकार UI थ्रेड में होने से पहले सूची अद्यतन ने मेरे लिए काम किया।

हालाँकि, जब मैं सूची को किसी अन्य ईवेंट / थ्रेड से अपडेट करता हूं - यानी ऐप के बाहर से कॉल, अपडेट UI थ्रेड में नहीं होगा और उसने getListView के लिए कॉल को अनदेखा कर दिया। ऊपर के रूप में runOnUiThread के साथ अद्यतन कॉलिंग ने मेरे लिए चाल चली। धन्यवाद!!


3

इसे इस्तेमाल करे

@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();
}

3
adpter.notifyDataSetInvalidated();

onPause()गतिविधि वर्ग की विधि में यह प्रयास करें ।



1

यदि आपकी सूची एडॉप्टर में ही समाहित है, तो फ़ंक्शन को अपडेट करने वाले फ़ंक्शन को कॉल करना चाहिए notifyDataSetChanged()

UI थ्रेड से इस फ़ंक्शन को चलाने से मेरे लिए चाल चली गई:

refresh()समारोह एडाप्टर के अंदर

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

फिर बदले में इस फ़ंक्शन को UI थ्रेड से चलाएं

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

यह वास्तव में मेरे लिए एक अंतर था क्योंकि अपडेट एक अलग धागे के माध्यम से नेटवर्क पर आया था।
चक

0

इस तरह कोशिश करें:

this.notifyDataSetChanged();

के बजाय:

adapter.notifyDataSetChanged();

आपको एडॉप्टर क्लास notifyDataSetChanged()में ListViewनहीं जाना है।


बेशक, यह एकमात्र मौका नहीं होगा, अगर गतिविधि को एक सूची द्वारा विस्तारित किया जाता है
cmario
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.