读书人

一个令人无比蛋疼的线程里更新ListVie

发布时间: 2012-08-08 14:32:45 作者: rapoo

一个令人无比蛋疼的线程里更新ListView的问题
弄了好几天了,想实现一个功能:显示一个ListView,在Activity的Create方法中开启一个新的线程,在线程里通过循环为一个自定义的ArrayAdapter类的add(使用父类的方法)方法增加数据,ListView已经使用setAdapter方法与自定义的ArrayAdapter绑定,希望在线程里为ArrayAdapter增加数据的同时,显示的ListView能同步显示出增加的数据,可是这么做后,会报Only the original thread that created a view hierarchy can touch its views的错误,并出现Force Close

最终希望达到的效果就是,ListView随着线程里ArrayAdapter数据项的逐步增加(故意增加延迟放慢循环),ListView一条一条的显示数据,并不影响主界面的其他操作。

我想可能是我的思路有问题,希望能熟悉Android开发的朋友们能帮帮我,谢谢了。

另外这个代码的ListView只能显示出ArrayAdapter的前10条数据的重复组合,虽然数据的总数貌似是对的,但是ListView的显示的是ArrayAdapter的前10条数据的重复随机组合,为什么会出现这种情况呢?

再次感谢各位了!谢谢!

贴出全部代码:

主Activity代码:

ListTest.java:

Java code
public class ListTest extends Activity {        private ListView lv;           /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        lv = (ListView)findViewById(R.id.list);                      //创建新线程用来显示列表        HandlerThread handlerThread = new HandlerThread("hthread_readcontact");        handlerThread.start(); //异步启动线程        //创建Handler        MyHandler myHandler = new MyHandler(handlerThread.getLooper());        //创建消息对象        Message msg = myHandler.obtainMessage();                //取出消息并执行        msg.sendToTarget();            }        //循环增加100个列表项    protected void AddListItem(){        List<PeopleInfo> myList = new ArrayList<PeopleInfo>();        MyAdapter ca = new MyAdapter(ListTest.this,myList);        //ca.setNotifyOnChange(true);        lv.setAdapter(ca);                for(int i=1;i<=100;i++){                        //增加记录            PeopleInfo pe = new PeopleInfo();            pe.setPeoleName("Fucker"+Integer.toString(i));            pe.setPeopleNum(Integer.toString(i));            System.out.println("i:"+Integer.toString(i));            System.out.println("PeopleInfo-->Name:"+pe.peopleName);            System.out.println("PeopleInfo-->Num :"+pe.peopleNum);            ca.add(pe);                        SystemClock.sleep(50L); //为了看到效果,故意增加一个延迟        }        ca.notifyDataSetChanged();    }        class MyHandler extends Handler{                        public MyHandler(){                            }                        public MyHandler(Looper looper){                super(looper);            }                @Override            public void handleMessage(Message msg) {                AddListItem();                System.out.println("Thread is runed!");            }    }     }


其他类代码:

MyAdapter.java:

Java code
public class MyAdapter extends ArrayAdapter<PeopleInfo> {    private LayoutInflater inflater;    List<PeopleInfo> itemList;    private static final int mResource = R.layout.contact_list; //xml布局文件    public MyAdapter(Context context,List<PeopleInfo> objects) {        super(context, mResource, objects);        // TODO Auto-generated constructor stub        inflater = LayoutInflater.from(context);        itemList = objects;    }        @Override    public void add(PeopleInfo object) {        // TODO Auto-generated method stub        super.add(object);        //itemList.add(object);    }    @Override    public void setNotifyOnChange(boolean notifyOnChange) {        // TODO Auto-generated method stub        super.setNotifyOnChange(notifyOnChange);    }    @Override    public Filter getFilter() {        // TODO Auto-generated method stub        return super.getFilter();    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        // TODO Auto-generated method stub        ViewHolder holder;        holder = new ViewHolder();                if(convertView == null){                    convertView = inflater.inflate(R.layout.contact_list, null);            //convertView = inflater.inflate(R.layout.listitem, null);                        holder.PhoneName = (TextView)convertView.findViewById(R.id.mname);            holder.PhoneNum = (TextView)convertView.findViewById(R.id.msisdn);                        convertView.setTag(holder);            holder.PhoneName.setText(itemList.get(position).getPeopleName());            holder.PhoneNum.setText(itemList.get(position).getPeopleNum());                    }                return convertView;    }        class ViewHolder{        TextView PhoneName;        TextView PhoneNum;    }} 



PeopleInfo.java:
Java code
public class PeopleInfo implements Serializable {    public String peopleName;    public String peopleNum;        public String getPeopleName(){        return peopleName;    }        public void setPeoleName(String peopleName){        this.peopleName=peopleName;    }        public String getPeopleNum(){        return peopleNum;    }        public void setPeopleNum(String peopleNum){        this.peopleNum = peopleNum;    }}




[解决办法]
如果是我,我想我会这么写。不知道是不是符合你的要求。
Java code
    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        mListView = (ListView)findViewById(R.id.list);        new Thread(new Runnable() {            public void run() {                mHandler.postDelayed((new Runnable() {                    public void run() {                        AddListItem();                    }                }), 1000);            }        }).start();    }
[解决办法]
还是给个例子吧,你这用法感觉非常奇怪(我说楼主):
Java code
    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        ArrayAdapter<String> ad = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, new Vector<String>());                mlv = new ListView(this);        mlv.setAdapter(ad);        setContentView(mlv);                mh = new Handler();        new Thread() {            @Override            public void run() {                // TODO Auto-generated method stub                for (int i = 0; i < 5; ++i) {                    First_Android.this.mh.post(new Runnable() {                        public void run() {                            // TODO Auto-generated method stub                            int n = new Random().nextInt();                                                        @SuppressWarnings("unchecked")                            ArrayAdapter<String> ad = (ArrayAdapter<String>) First_Android.this.mlv.getAdapter();                            ad.add(Integer.toString(n));                            ad.notifyDataSetChanged();                        }                    });                                        try {                        sleep(1000);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }            }        }.start();
[解决办法]
按照你的要求修改了一下,你代码最大的问题就是在Handler的处理过程中加入了Sleep,等于把主线程阻塞了,导致界面绘制不畅。
Java code
public class ListTest extends Activity {    private ListView mListView;    Handler mHandler = new Handler();    List<PeopleInfo> mList = null;    MyAdapter mAdapter = null;    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        mListView = (ListView)findViewById(R.id.list);        mList = new ArrayList<PeopleInfo>();        mAdapter = new MyAdapter(ListTest.this, mList);        mListView.setAdapter(mAdapter);        new Thread(new Runnable() {            public void run() {                while (true) {                    mHandler.post(new Runnable() {                        public void run() {                            AddListItem();                        }                    });                    try {                        Thread.sleep(500);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }            }        }).start();    }    // 循环增加100个列表项    protected void AddListItem() {        // 增加记录        PeopleInfo pe = new PeopleInfo();        int number = (int)(Math.random() * 1000);        pe.setPeoleName("Haha " + Integer.toString(number));        pe.setPeopleNum(Integer.toString(number));        System.out.println("i:" + Integer.toString(number));        System.out.println("PeopleInfo-->Name:" + pe.peopleName);        System.out.println("PeopleInfo-->Num :" + pe.peopleNum);        mAdapter.add(pe);//        SystemClock.sleep(1000); // 为了看到效果,故意增加一个延迟        mAdapter.notifyDataSetChanged();    }} 


[解决办法]
ListTest:
public class ListTest extends Activity {
//-------------------------------
private Thread myThread = new Thread(){
@Override
public void run () {
AddListItem();
}
};
//------------------------------

private MyHandler myHandler = new MyHandler();
private ListView lv;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv = (ListView)findViewById(R.id.list);


// //创建新线程用来显示列表
// HandlerThread handlerThread = new HandlerThread("hthread_readcontact");
// handlerThread.start(); //异步启动线程
// //创建Handler
// MyHandler myHandler = new MyHandler(handlerThread.getLooper());
// //创建消息对象
// Message msg = myHandler.obtainMessage();
//
// //取出消息并执行
// msg.sendToTarget();

//----------------------------------

List<PeopleInfo> myList = new ArrayList<PeopleInfo>();
MyAdapter ca = new MyAdapter(this, myList);
lv.setAdapter(ca);

myThread.start();
//------------------------------------
}

//循环增加100个列表项
protected void AddListItem(){
// List<PeopleInfo> myList = new ArrayList<PeopleInfo>();
// MyAdapter ca = new MyAdapter(ListTest.this,myList);
// //ca.setNotifyOnChange(true);
// lv.setAdapter(ca);


for(int i=1;i<=100;i++){

//增加记录
// PeopleInfo pe = new PeopleInfo();
// pe.setPeopleName("Fucker"+Integer.toString(i));
// pe.setPeopleNum(Integer.toString(i));
// System.out.println("i:"+Integer.toString(i));
// System.out.println("PeopleInfo-->Name:"+pe.peopleName);
// System.out.println("PeopleInfo-->Num :"+pe.peopleNum);

//-----------------------------------
Message m = new Message();
Bundle data = new Bundle();
data.putString("name", "Fucker" + i);
data.putString("number", "" + i);
m.setData(data);
myHandler.sendMessage(m);
//------------------------------------

SystemClock.sleep(200L); //为了看到效果,故意增加一个延迟
}
//ca.notifyDataSetChanged();

}
class MyHandler extends Handler{

public MyHandler(){

}

public MyHandler(Looper looper){
super(looper);
}

@Override
public void handleMessage(Message msg) {
// AddListItem();
// System.out.println("Thread is runed!");

//----------------------------------
if (null == msg)
return;
PeopleInfo pe = new PeopleInfo();
Bundle data = msg.getData();
pe.setPeopleName(data.getString("name"));
pe.setPeopleNum(data.getString("number"));
Log.v("================", data.getString("name")+" "+data.getString("number"));
MyAdapter ad = (MyAdapter) lv.getAdapter();
ad.add(pe);


ad.notifyDataSetChanged();
//-------------------------------------
}
}
}

MyAdapter:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub

if(convertView == null){
ViewHolder holder;
holder = new ViewHolder();

convertView = inflater.inflate(R.layout.contact_list, null);
//convertView = inflater.inflate(R.layout.listitem, null);

holder.PhoneName = (TextView)convertView.findViewById(R.id.mname);
holder.PhoneNum = (TextView)convertView.findViewById(R.id.msisdn);

convertView.setTag(holder);
holder.PhoneName.setText(itemList.get(position).getPeopleName());
holder.PhoneNum.setText(itemList.get(position).getPeopleNum());

}
//-------------------------------------
else {
ViewHolder h = (ViewHolder) convertView.getTag();
h.PhoneName.setText(itemList.get(position).getPeopleName());
h.PhoneNum.setText(itemList.get(position).getPeopleNum());
}
//-------------------------------------
return convertView;
}

读书人网 >Android

热点推荐