Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android ListView cotent of the adapter has changed but ListView did not receive a notification

Android ListView cotent of the adapter has changed but ListView did not receive a notification

編輯:關於Android編程

前段時間完成某項目離線數據部分時,用了大量ListView顯示加載數據,在碰到大數據量的加載時容易出現的錯誤。即我們將List作為參數傳遞給ListView的Adapter,同時在開辟線程加載數據時直接對剛剛參數傳遞的List操作,具體代碼如下:

 

[java] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px">package com.jackchan.listtest; 
 
import java.util.ArrayList; 
import java.util.List; 
 
import android.app.Activity; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.ViewGroup; 
import android.widget.BaseAdapter; 
import android.widget.Button; 
import android.widget.ListView; 
import android.widget.TextView; 
 
public class ListTestActivity extends Activity { 
     
    private ListView mListView; 
    private Button mBtn; 
    private int text = 0; 
    private List<String> mList; 
    private MyAdapter mAdapter; 
    private List<String> mListBak; 
     
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        mListView = (ListView)findViewById(R.id.listview); 
        mBtn = (Button)findViewById(R.id.btn); 
        mList = new ArrayList<String>(); 
  //      mListBak = new ArrayList<String>();  
        mAdapter = new MyAdapter(mList); 
        mListView.setAdapter(mAdapter); 
        mBtn.setOnClickListener(new OnClickListener() { 
             
            @Override 
            public void onClick(View v) { 
                // TODO Auto-generated method stub  
                GetDataTask task = new GetDataTask(); 
                task.execute(new Void[0]); 
            } 
        }); 
    } 
     
    private class GetDataTask extends AsyncTask<Void, Void, Void>{ 
 
        @Override 
        protected Void doInBackground(Void... params) { 
        //  mListBak.clear();  
            mList.clear(); 
            for(int i = 0; i < 50; i++){ 
                try { 
                    Thread.sleep(50); 
                } catch (InterruptedException e) { 
                    // TODO Auto-generated catch block  
                    e.printStackTrace(); 
                } 
            //  mListBak.add(text+"");  
                mList.add(text+""); 
                text++; 
            } 
            return null; 
        } 
 
        @Override 
        protected void onPostExecute(Void result) { 
            super.onPostExecute(result); 
        //  mAdapter.addList(mListBak);  
            mAdapter.notifyDataSetChanged(); 
        } 
         
         
    } 
     
    private class MyAdapter extends BaseAdapter{ 
         
        private TextView mItem; 
        private List<String> mData; 
         
         
        public MyAdapter(List<String> data) { 
            this.mData = data; 
        } 
 
        @Override 
        public int getCount() { 
            // TODO Auto-generated method stub  
            return mData.size(); 
        } 
 
        @Override 
        public Object getItem(int arg0) { 
            // TODO Auto-generated method stub  
            return null; 
        } 
 
        @Override 
        public long getItemId(int position) { 
            // TODO Auto-generated method stub  
            return position; 
        } 
 
        @Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            if(convertView == null){ 
                convertView = LayoutInflater.from(ListTestActivity.this).inflate(R.layout.item, null); 
                mItem = (TextView)convertView.findViewById(R.id.item); 
                convertView.setTag(mItem); 
            } 
            else{ 
                mItem = (TextView)convertView.getTag(); 
            } 
            mItem.setText(mData.get(position)); 
            return convertView; 
        }  
         
        public void addList(List list){ 
            mData.addAll(list); 
        } 
    } 

</SPAN> 

package com.jackchan.listtest;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

public class ListTestActivity extends Activity {
 
 private ListView mListView;
 private Button mBtn;
 private int text = 0;
 private List<String> mList;
 private MyAdapter mAdapter;
 private List<String> mListBak;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mListView = (ListView)findViewById(R.id.listview);
        mBtn = (Button)findViewById(R.id.btn);
        mList = new ArrayList<String>();
  //      mListBak = new ArrayList<String>();
        mAdapter = new MyAdapter(mList);
        mListView.setAdapter(mAdapter);
        mBtn.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    // TODO Auto-generated method stub
    GetDataTask task = new GetDataTask();
    task.execute(new Void[0]);
   }
  });
    }
   
    private class GetDataTask extends AsyncTask<Void, Void, Void>{

  @Override
  protected Void doInBackground(Void... params) {
  // mListBak.clear();
   mList.clear();
   for(int i = 0; i < 50; i++){
    try {
     Thread.sleep(50);
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   // mListBak.add(text+"");
    mList.add(text+"");
    text++;
   }
   return null;
  }

  @Override
  protected void onPostExecute(Void result) {
   super.onPostExecute(result);
  // mAdapter.addList(mListBak);
   mAdapter.notifyDataSetChanged();
  }
     
  
    }
   
    private class MyAdapter extends BaseAdapter{
     
     private TextView mItem;
     private List<String> mData;
     
     
  public MyAdapter(List<String> data) {
   this.mData = data;
  }

  @Override
  public int getCount() {
   // TODO Auto-generated method stub
   return mData.size();
  }

  @Override
  public Object getItem(int arg0) {
   // TODO Auto-generated method stub
   return null;
  }

  @Override
  public long getItemId(int position) {
   // TODO Auto-generated method stub
   return position;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
   if(convertView == null){
    convertView = LayoutInflater.from(ListTestActivity.this).inflate(R.layout.item, null);
    mItem = (TextView)convertView.findViewById(R.id.item);
    convertView.setTag(mItem);
   }
   else{
    mItem = (TextView)convertView.getTag();
   }
   mItem.setText(mData.get(position));
   return convertView;
  }
     
  public void addList(List list){
   mData.addAll(list);
  }
    }
}

 


這段代碼在執行時,如果你在GetDataTask執行doInBackground的時候,去滑動屏幕的ListView,很容易出現

The content of the adapter has changed but ListView did not receive a notification.

Make sure the content of your adapter is not modified from a background thread, but only from the UI thread.

的系統崩潰錯誤,這段話的意思就是說適配器的內容發生變化,但ListView沒有收到通知,確保適配器的內容只在UI線程更新不要再後台線程更新。

而我們的程序無論是在UI線程還是異步GetDataTask裡都是直接對適配器內容mList進行操作,所以會出現錯誤。

 

規避以上錯誤的具體方法是:

1、重新分配一個List對象專門在異步任務裡加載數據;

2、在異步任務結束後在UI線程把新分配的List的內容添加到適配器的list裡;

3、在UI線程裡適配器執行notifyDataSetChanged()更新數據

 

上面的代碼更改如下


[java] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px">package com.jackchan.listtest; 
 
import java.util.ArrayList; 
import java.util.List; 
 
import android.app.Activity; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.ViewGroup; 
import android.widget.BaseAdapter; 
import android.widget.Button; 
import android.widget.ListView; 
import android.widget.TextView; 
 
public class ListTestActivity extends Activity { 
     
    private ListView mListView; 
    private Button mBtn; 
    private int text = 0; 
    private List<String> mList; 
    private MyAdapter mAdapter; 
    private List<String> mListBak; 
     
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        mListView = (ListView)findViewById(R.id.listview); 
        mBtn = (Button)findViewById(R.id.btn); 
        mList = new ArrayList<String>(); 
        mListBak = new ArrayList<String>(); 
        mAdapter = new MyAdapter(mList); 
        mListView.setAdapter(mAdapter); 
        mBtn.setOnClickListener(new OnClickListener() { 
             
            @Override 
            public void onClick(View v) { 
                // TODO Auto-generated method stub  
                GetDataTask task = new GetDataTask(); 
                task.execute(new Void[0]); 
            } 
        }); 
    } 
     
    private class GetDataTask extends AsyncTask<Void, Void, Void>{ 
 
        @Override 
        protected Void doInBackground(Void... params) { 
            mListBak.clear(); 
        //  mList.clear();  
            for(int i = 0; i < 50; i++){ 
                try { 
                    Thread.sleep(50); 
                } catch (InterruptedException e) { 
                    // TODO Auto-generated catch block  
                    e.printStackTrace(); 
                } 
                mListBak.add(text+""); 
            //  mList.add(text+"");  
                text++; 
            } 
            return null; 
        } 
 
        @Override 
        protected void onPostExecute(Void result) { 
            super.onPostExecute(result); 
            mAdapter.addList(mListBak); 
            mAdapter.notifyDataSetChanged(); 
        } 
         
         
    } 
     
    private class MyAdapter extends BaseAdapter{ 
         
        private TextView mItem; 
        private List<String> mData; 
         
         
        public MyAdapter(List<String> data) { 
            this.mData = data; 
        } 
 
        @Override 
        public int getCount() { 
            // TODO Auto-generated method stub  
            return mData.size(); 
        } 
 
        @Override 
        public Object getItem(int arg0) { 
            // TODO Auto-generated method stub  
            return null; 
        } 
 
        @Override 
        public long getItemId(int position) { 
            // TODO Auto-generated method stub  
            return position; 
        } 
 
        @Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            if(convertView == null){ 
                convertView = LayoutInflater.from(ListTestActivity.this).inflate(R.layout.item, null); 
                mItem = (TextView)convertView.findViewById(R.id.item); 
                convertView.setTag(mItem); 
            } 
            else{ 
                mItem = (TextView)convertView.getTag(); 
            } 
            mItem.setText(mData.get(position)); 
            return convertView; 
        }  
         
        public void addList(List list){ 
            mData.addAll(list); 
        } 
    } 

</SPAN> 

package com.jackchan.listtest;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

public class ListTestActivity extends Activity {
 
 private ListView mListView;
 private Button mBtn;
 private int text = 0;
 private List<String> mList;
 private MyAdapter mAdapter;
 private List<String> mListBak;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mListView = (ListView)findViewById(R.id.listview);
        mBtn = (Button)findViewById(R.id.btn);
        mList = new ArrayList<String>();
        mListBak = new ArrayList<String>();
        mAdapter = new MyAdapter(mList);
        mListView.setAdapter(mAdapter);
        mBtn.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    // TODO Auto-generated method stub
    GetDataTask task = new GetDataTask();
    task.execute(new Void[0]);
   }
  });
    }
   
    private class GetDataTask extends AsyncTask<Void, Void, Void>{

  @Override
  protected Void doInBackground(Void... params) {
   mListBak.clear();
  // mList.clear();
   for(int i = 0; i < 50; i++){
    try {
     Thread.sleep(50);
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    mListBak.add(text+"");
   // mList.add(text+"");
    text++;
   }
   return null;
  }

  @Override
  protected void onPostExecute(Void result) {
   super.onPostExecute(result);
   mAdapter.addList(mListBak);
   mAdapter.notifyDataSetChanged();
  }
     
  
    }
   
    private class MyAdapter extends BaseAdapter{
     
     private TextView mItem;
     private List<String> mData;
     
     
  public MyAdapter(List<String> data) {
   this.mData = data;
  }

  @Override
  public int getCount() {
   // TODO Auto-generated method stub
   return mData.size();
  }

  @Override
  public Object getItem(int arg0) {
   // TODO Auto-generated method stub
   return null;
  }

  @Override
  public long getItemId(int position) {
   // TODO Auto-generated method stub
   return position;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
   if(convertView == null){
    convertView = LayoutInflater.from(ListTestActivity.this).inflate(R.layout.item, null);
    mItem = (TextView)convertView.findViewById(R.id.item);
    convertView.setTag(mItem);
   }
   else{
    mItem = (TextView)convertView.getTag();
   }
   mItem.setText(mData.get(position));
   return convertView;
  }
     
  public void addList(List list){
   mData.addAll(list);
  }
    }
}


 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved