zoukankan      html  css  js  c++  java
  • ListView中使用自定义Adapter及时更xin

    在项目中,遇到不能ListView及时更新的问题。写了一个demo,其中也遇到一些问题,一并写出来。好吧,上代码:

    public class PersonAdapter extends BaseAdapter { 
        private ArrayList<PersonBean> mList; 
        private Context mContext; 
           
        public PersonAdapter(ArrayList<PersonBean> list, Context context) { 
            mList = list; 
            mContext = context; 
        } 
           
        public void refresh(ArrayList<PersonBean> list) { 
            mList = list; 
            notifyDataSetChanged(); 
        } 
           
       
        @Override 
        public int getCount() { 
            return mList.size(); 
        } 
       
        @Override 
        public Object getItem(int position) { 
            return mList.get(position); 
        } 
       
        @Override 
        public long getItemId(int position) { 
            return position; 
        } 
       
        @Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            Holder holder = null; 
            if (convertView == null) { 
                LayoutInflater inflater = LayoutInflater.from(mContext); 
                convertView = inflater.inflate(R.layout.list_item, null); 
                holder = new Holder(); 
                holder.mNameText = (TextView)convertView.findViewById(R.id.name_text); 
                holder.mIDText = (TextView)convertView.findViewById(R.id.id_text); 
                convertView.setTag(holder); 
            } else { 
                holder = (Holder) convertView.getTag(); 
            } 
            holder.mNameText.setText(mList.get(getCount() - position - 1).getName()); 
            holder.mIDText.setText(mList.get(getCount() - position - 1).getID()); 
            return convertView; 
        } 
       
        class Holder { 
            private TextView mNameText, mIDText; 
        } 
    }

     

    PersonAdapter继承自BaseAdapter,里面的代码都应该比较熟悉。里面注意这点代码:

    public void refresh(ArrayList<PersonBean> list) { 

            mList = list; 

            notifyDataSetChanged(); 

        }

     

    在初始化PersonAdapter的时候,需要外部导入一个mList。

    public PersonAdapter(ArrayList<PersonBean> list, Context context) { 

            mList = list; 

            mContext = context; 

        }

    在使用这种类型时,在Activity使用mAdapter.notifyDataSetChanged()时候,有时候会发现数据不能够及时的更新。这个时候,就比较需要调用refresh()这个方法了。

    下面看一下主Activity:

    public class ListViewRefreshActivity extends Activity { 
       
        private ListView mListView; 
        private ArrayList<PersonBean> mList; 
        private PersonAdapter mAdapter; 
        private Handler mHandler; 
        private String mName, mID; 
       
        @Override 
        public void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            setContentView(R.layout.main); 
       
            mListView = (ListView)findViewById(R.id.listView); 
            mList = new ArrayList<PersonBean>(); 
            mAdapter = new PersonAdapter(mList, ListViewRefreshActivity.this); 
            mListView.setAdapter(mAdapter); 
       
            mHandler = new Handler() { 
       
                @Override 
                public void handleMessage(Message msg) { 
                    super.handleMessage(msg); 
                    mList.add((PersonBean) msg.obj); 
                    Log.v("@@@@@@", "this is get message"); 
                    mAdapter.refresh(mList); 
    //              mAdapter.notifyDataSetChanged(); 
                } 
            }; 
       
    //      final Message message = new Message(); 
            new Thread(new Runnable() { 
       
                @Override 
                public void run() { 
                    try { 
                        for (int i = 0; i < 10; i++) { 
                            mName = "hao :" + i; 
                            mID = "" + i; 
                            PersonBean bean = new PersonBean(); 
                            bean.setID(mID); 
                            bean.setName(mName); 
                            Message message = new Message(); 
                            message.obj = bean; 
                            Thread.sleep(3000); 
                            mHandler.sendMessage(message); 
    //                      mHandler.sendMessageDelayed(message, 10000); 
                        }}catch (Exception e) { 
                            e.printStackTrace(); 
                        } 
                } 
            }).start(); 
        } 
    }

    如果用这个message,注释run方法体内的message

    ,运行程序,在我机子上,发送第四个消息时,就会报android.util.AndroidRuntimeException:This message is already in use这个错,message已经被使用。所以,每一次发送,都要重新创建一个新的message。也可以使用一下语句:

    message = mHandler.obtainMessage();

    里面主要看一下handler中重写handlerMessage这个方法:

    1

    2

    3

    4

    5

    6

    7

    8

    @Override 

                public void handleMessage(Message msg) { 

                    super.handleMessage(msg); 

                    mList.add((PersonBean) msg.obj); 

                    Log.v("@@@@@@", "this is get message"); 

                    mAdapter.refresh(mList); 

    //              mAdapter.notifyDataSetChanged(); 

                }

    当然,在这个小例子中,使用mAdapter.refresh这个方法更麻烦点,直接调用notifyDataSetChange就可以达到效果,如果你的代码里面不能达到效果,就可以使用mAdapter.refresh试一下。

     

    notifyDataSetChanged这个方法的设计是典型观察者模式。看一下源代码:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { 

        private final DataSetObservable mDataSetObservable = new DataSetObservable(); 

       

        public boolean hasStableIds() { 

            return false

        } 

           

        public void registerDataSetObserver(DataSetObserver observer) { 

            mDataSetObservable.registerObserver(observer); 

        } 

       

        public void unregisterDataSetObserver(DataSetObserver observer) { 

            mDataSetObservable.unregisterObserver(observer); 

        } 

           

        /** 

         * Notifies the attached observers that the underlying data has been changed 

         * and any View reflecting the data set should refresh itself. 

         */

        public void notifyDataSetChanged() { 

            mDataSetObservable.notifyChanged(); 

        } 

       

        /** 

         * Notifies the attached observers that the underlying data is no longer valid 

         * or available. Once invoked this adapter is no longer valid and should 

         * not report further data set changes. 

         */

        public void notifyDataSetInvalidated() { 

            mDataSetObservable.notifyInvalidated(); 

        }

     有一个数据被观察者:mDataSetObservable。当被观察者数据发生改变时,通知观察者。我们使用registerDataSetObserver这个方法注册观察者。都是调用notifyDataSetChanged方法。就是告诉观察者,数据有所改变。在这个方法中,又调用了DataSetObserveable的notifyChanged方法:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    /** 

         * Invokes onChanged on each observer. Called when the data set being observed has 

         * changed, and which when read contains the new state of the data. 

         */

        public void notifyChanged() { 

            synchronized(mObservers) { 

                // since onChanged() is implemented by the app, it could do anything, including 

                // removing itself from {@link mObservers} - and that could cause problems if 

                // an iterator is used on the ArrayList {@link mObservers}. 

                // to avoid such problems, just march thru the list in the reverse order. 

                for (int i = mObservers.size() - 1; i >= 0; i--) { 

                    mObservers.get(i).onChanged(); 

                } 

            } 

        }

  • 相关阅读:
    在C#中使用正则表达式
    C++流操纵算子(格式控制)
    linux(Fedora) doxygen 的安装和使用
    UTF8
    java cookie全解析
    Fedora16 安装Adobe Flash Player方法
    工程素养
    感悟数据封装
    谷歌如何保护隐私
    openCV画的词法分析图
  • 原文地址:https://www.cnblogs.com/linximeng/p/3751913.html
Copyright © 2011-2022 走看看