Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android--UI--listview使用和優化

android--UI--listview使用和優化

編輯:關於Android編程

listview一般使用步驟:

1.定制實體類,加入要填入list的變量,設置好set,get方法。
2.自定義item布局,根據要填入的數據。
3.自定義適配器類,繼承ArrayAdapter。
4.MainActivity中給listview綁定adapter並·添加數據
實體類:

public class Wanwan {
    private  String name;
    private int imgid;

    public Wanwan(String name,int imgid){
        this.name=name;
        this.imgid=imgid;

    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getImgid() {
        return imgid;
    }

    public void setImgid(int imgid) {
        this.imgid = imgid;
    }
}

自定義adpater類

public class WanwanAdapter extends ArrayAdapter {
    private int resourceID;
    public WanwanAdapter(Context context, int textviewresourceid, List object){
        super(context,textviewresourceid,object);
        resourceID=textviewresourceid;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Wanwan wanwan=getItem(position);//獲取當前項的wanwan實例
        View view= LayoutInflater.from(getContext()).inflate(resourceID,null);//獲取view實例
        ImageView imgview=(ImageView) view.findViewById(R.id.img_wanwan);
        TextView textView=(TextView) view.findViewById(R.id.text_wanwan);
        imgview.setImageResource(wanwan.getImgid());
        textView.setText(wanwan.getName());
        return view;
    }
}

布局文件:item_xml




    

    

MainActivity

public class MainActivity extends AppCompatActivity {
    private List wananlist=new ArrayList();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        iniWanwan();//列表添加數據
        WanwanAdapter wanwanAdapter=new WanwanAdapter(MainActivity.this,R.layout.wanwan_item,wananlist);
        ListView listView=(ListView) findViewById(R.id.listview);
        listView.setAdapter(wanwanAdapter);
    }
    private void iniWanwan(){
        for(int i=0;i<100;i++){
            wananlist.add(new Wanwan("wanwan", R.mipmap.ic_launcher));
        }
    }
}

運行:
這裡寫圖片描述

關於優化listview

自定義的adapter,會要重寫getView方法,在getView方法產生給用戶item的視圖以及數據。
這裡有一個優化的地方,就是重用view,這樣減少內存消耗,同時加快item加載速度。

1.使用convertView參數優化

convert參數用於將之前加載好的緩存,重用了,很大程度上的減少了內存的消耗。通過判斷convertView是否為null,是的話就需要產生一個視圖出來,然後給這個視圖數據,最後將這個視圖返回給底層,呈獻給用戶。
特點:如果當前的convertView為null,則通過LayoutInflat產生一個view。
修改adpater代碼:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Wanwan wanwan = getItem(position);//獲取當前項的wanwan實例
        View view;
        if (convertView == null) {
            view = LayoutInflater.from(getContext()).inflate(resourceID, null);//獲取view實例
        } else {
            view = convertView;
        }
        ImageView imgview = (ImageView) view.findViewById(R.id.img_wanwan);
        TextView textView = (TextView) view.findViewById(R.id.text_wanwan);
        imgview.setImageResource(wanwan.getImgid());
        textView.setText(wanwan.getName());
        return view;
    }

2.設置classViewHolder,防止重復尋找控件

上面的寫法會有一個缺點,就是每次在getVIew的時候,都需要重新的findViewById,重新找到控件,然後進行控件的賦值以及事件相應設置。這樣其實在做重復的事情,因為的geiview中,其實包含有這些控件,而且這些控件的id還都是一樣的,也就是其實只要在view中findViewById一次,後面無需要每次都要findViewById了。
所以我們要自定義一個類 ViewHolder
代碼修改:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Wanwan wanwan = getItem(position);//獲取當前項的wanwan實例
        View view;
        ViewHolder viewHolder;
        if (convertView == null) {
            view = LayoutInflater.from(getContext()).inflate(resourceID, null);//獲取view實例
            viewHolder=new ViewHolder();
            viewHolder.imageView=(ImageView) view.findViewById(R.id.img_wanwan);//實例化變量
            viewHolder.textView=(TextView) view.findViewById(R.id.text_wanwan);
            view.setTag(viewHolder);//將Viewholder存儲在view中
        } else {
            view = convertView;
            viewHolder=(ViewHolder) view.getTag();//重新獲取viewholder
        }
        //ImageView imgview = (ImageView) view.findViewById(R.id.img_wanwan);
        //TextView textView = (TextView) view.findViewById(R.id.text_wanwan);
        viewHolder.imageView.setImageResource(wanwan.getImgid());
        viewHolder.textView.setText(wanwan.getName());
        return view;
    }
    class ViewHolder{
        ImageView imageView;
        TextView textView;
    }

PS:以上兩種優化方式參考《第一行代碼》

3.其他優化建議

1.設置ViewHolder為static,也就是靜態的,靜態類只會在第一次加載時會耗費比較長時間,但是後面就可以很好幫助加載,同時保證了內存中只有一個ViewHolder,節省了內存的開銷。

static class ViewHolder{
        ImageView imageView;
        TextView textView;
    }

4.大量分批/網絡下載

如果有很多item並且需要從網絡下載數據的話。一次性全加載不僅浪費時間而且消耗用戶流量。

其一:假如網絡情況很好,我們使用的手機也許能夠一下子加載完所有新聞數據,然後顯示在ListView中,用戶可能感覺還好,假如說在網絡不太順暢的情況下,用戶加載完所有網絡的數據,可能這個list是1000條新聞,那麼用戶可能需要面對一個空白的Activity好幾分鐘,這個顯然是不合適的
其二:我們知道Android虛擬機給每個應用分配的運行時內存是一定的,一般性能不太好的機器只有16M,好一點的可能也就是64M的樣子,假如說我們現在要浏覽的新聞總數為一萬條,即便是網絡很好的情況下,我們可以很快的加載完畢,但是多數情況下也會出現內存溢出從而導致應用崩潰的情況。

為此搜索了一下:
原理就是

listview.setOnScrollListener(new scrollListener());

判斷滑動的item個數,到一定時候就繼續加載。

實現代碼:
footer.xml



    

    

網絡服務類:

public class DataService {
    /**
     *
     * @param startposition
     *            :從第startposition條數據開始加載
     * @param pagesize
     *            :每頁顯示數量
     * @return:服務器返回數組
     */
    public static List<string> getData(int startposition, int pagesize) {
        List<string> list = new ArrayList<string>();
        for (int i = startposition; i <startposition+ i="" return="" pre="">

主要代碼;

public class MainActivity extends AppCompatActivity {
//    private List wananlist=new ArrayList();
    private ListView listview;
    private List data = new ArrayList();
    private ArrayAdapter adapter;
    private LayoutInflater inflater;
    private View footer;// 頁腳-正在加載中.....
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

//        iniWanwan();//列表添加數據
//        WanwanAdapter wanwanAdapter=new WanwanAdapter(MainActivity.this,R.layout.wanwan_item,wananlist);
//        ListView listView=(ListView) findViewById(R.id.listview);
//        listView.setAdapter(wanwanAdapter);

        inflater = getLayoutInflater();
        footer = inflater.inflate(R.layout.footer, null);
        listview = (ListView) findViewById(R.id.listview);
        listview.setOnScrollListener(new scrollListener());
        data.addAll(DataService.getData(0, 20));
        adapter = new ArrayAdapter(this,
                android.R.layout.simple_list_item_1, data);
        /* 在適配器之前加頁腳,這樣適配器會重新被封裝成 '有頁腳的適配器' */
        listview.addFooterView(footer);
        listview.setAdapter(adapter);
        listview.removeFooterView(footer);
    }

    /**
     * listview滾動監聽類
     *
     */
    public class scrollListener implements AbsListView.OnScrollListener {

        int pagesize = 20;// 每頁顯示條目
        int maxpage = 5;// 最多頁數
        int currentpage;// 當前頁
        int nextpage;
        boolean finish_load = true;// 加載是否完成,默認完成

        /**
         * 監聽滾動狀態改變:1-手指正在滑動 2-手指停止滑動 3-組件停止滾動
         */
        public void onScrollStateChanged(AbsListView view, int scrollState) {
        }

        /**
         * firstVisibleItem:第一個可見item visibleItemCount:可見item數量
         * totalItemCount:總條目數量
         */
        public void onScroll(AbsListView view, int firstVisibleItem,
                             int visibleItemCount, int totalItemCount) {
            final int total = totalItemCount;
            /* 如果滾動到最後一條 */
            if (listview.getLastVisiblePosition() + 1 == totalItemCount) {
                if (totalItemCount > 0) {
                    /* 獲取當前頁 */
                    currentpage = totalItemCount % pagesize == 0 ? totalItemCount
                            / pagesize
                            : totalItemCount / pagesize + 1;
                    nextpage = currentpage + 1;
                    /*
                     * 如果當前頁小於規定的最大頁數,並且加載完成(不斷滾動就會不斷執行onScroll方法,
                     * 所以用finish_load鎖定翻頁)
                     */
                    if (nextpage <= maxpage && finish_load) {
                        finish_load = false;
                        /* 每次翻頁前添加頁腳 */
                        listview.addFooterView(footer);
                        /* 創建子線程,執行翻頁 */
                        new Thread(new Runnable() {
                            public void run() {
                                try {
                                    Thread.sleep(3000);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                                List l = DataService.getData(total,
                                        pagesize);
                                handle.sendMessage(handle.obtainMessage(123, l));
                            }
                        }).start();
                    }

                }
            }
        }

        /* 通過handle和主線程通訊,主線程接收消息更新UI */
        Handler handle = new Handler() {
            public void handleMessage(Message msg) {
                data.addAll((List) msg.obj);
                adapter.notifyDataSetChanged();
                /* 頁腳顯示完就刪掉 */
                if (listview.getFooterViewsCount() > 0)
                    listview.removeFooterView(footer);
                finish_load = true;
            }
        };
    }
//    private void iniWanwan(){
//        for(int i=0;i<100;i++){
//            wananlist.add(new Wanwan("wanwan", R.mipmap.ic_launcher));
//        }
//    }
}

實現效果; 這裡寫圖片描述

DEMO下載:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD48cD48YSBkYXRhLWNrZS1zYXZlZC1ocmVmPQ=="https://github.com/HuRuWo/android/tree/master/listview-youhua" href="https://github.com/HuRuWo/android/tree/master/listview-youhua">ListView優化 AandroidStudio2.1.2打開

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