手记

ListView深入学习

1、ListView分页加载

        <1>分页的作用

                (1)避免一次性加载过多内容时,造成内存溢出;

                (2)可以增强用户体验。

        <2>实现思路

                (1)当滚动到最后一条的时候,加载新数据;

                (2)适配器的数据源要进行累加:listDatas.addAll(list)

                (3)数据发生变化时,适配器及时通知:adapter.notifyDataSetChanged()

                (4)判断是否滚到了最后一行

1.  if (firstVisibleItem + visibleItemCount == totalItemCount ) {   

2.    isBottom = true;

3.  }

        <3>实例步骤

                (1)模拟1000条数据,以分页方式显示;

                (2)使用BaseAdapter自定义适配器显示数据;

                (3)在ListView下方增加“显示更多”按钮以实现加载下一页数据;

                (4)ListView.setOnScrollListener()方法设置滚动事件监听器;

                (5)通过滚动事件监听器判断是否滚动到最底部,若在底部则显示“显示更多“按钮;

                (6)点击“显示更多”按钮,根据当前的页码与一页显示的记录数,加载数据;

                (7)将加载的数据追加到适配器的数据源中

2、AdapterView.OnItemClickListener 列表项点击事件监听器:onItemClick(AdapterView<?> parent, View view, int position, long id)

3、OnScrollListener 滚动事件监听器

        <1>onScrollStateChanged(AbsListView view, int scrollState):监听屏幕的滚动状态的变动情况

                (1)scrollState状态说明:

                           SCROLL_STATE_TOUCH_SCROLL(1):

                            表示正在滚动。当屏幕滚动且用户使用的触碰或手指还在屏幕上时为1

                          SCROLL_STATE_FLING(2) :

                            表示手指做了抛的动作(手指离开屏幕前,用力滑了一下,屏幕产生惯性滑动)。

                          SCROLL_STATE_IDLE(0) :

                            表示屏幕已停止。屏幕停止滚动时为0。

        <2>onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount):监听屏幕滚动的item的数量

                (1)AbsListView : 当前滚动的ListView控件

                (2)firstVisibleItem:当前窗口中能看见ListView的第一个列表项ID(从0开始)   

                (3)visibleItemCount:当前窗口中能看见的ListView列表项的个数(小半个也算)   

                (4)totalItemCount:ListView列表项的总数

4、ListView的优化

        <1>ListView的高度属性设置

                (1)设置为"wrap_content"时,getView()方法一般会执行3次左右;

                (2)建议设置为"match_parent"或固定值,避免重复计算ListView的高度。

        <2>ViewHolder的使用,将findViewById()获取的控件封装起来,便于复用

        <3>convertView的复用

                (1)converView如何产生的?

                            Android中有个叫做Recycler的构件,下图是他的工作原理:

                            a、如果你有100个item,其中只有可见的项目存在内存中,其他的在Recycler中。

                            b、ListView先请求一个type1视图(getView),然后请求其他可见的item,convertView在getView中是空(null)的。

                            c、当item1滚出屏幕,并且一个新的item从屏幕底端上来时,ListView再请求一个type1视图,convertView此时不是空值了,它的值是item1。你只需设定新的数据,然后返回convertView,不必重新创建一个视图。

                (2)优点:减少getView()时通过infalter加载布局的次数,减少内存开销,提高性能

                (3)缺点:若使用异步任务下载图片时,可能会出现图片错位问题,因为convertView的位置可能是第一个

         <4>View的标签tag属性

                (1)同id属性一样,标识控件的唯一性

                (2)View.setTag(Object)设置控件的标签

                (3)View.getTag()获取控件的标签

                (4)View.setTag()+ViewHolder+convertView复用,减少布局加载和findViewBy的次数,降低的内存开销,提升性能

5、ListView实现图文混排

        <1>实现思路

                (1)创建图文混排的Item布局文件

1.  <?xml version="1.0" encoding="utf-8"?>

2.  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

3.      android:layout_width="match_parent"

4.      android:layout_height="match_parent"

5.      android:orientation="vertical" >

6.      

7.   

8.      <ImageView

9.          android:id="@+id/img"

10.         android:layout_width="80dp"

11.         android:layout_height="80dp"

12.         android:scaleType="fitXY"

13.         android:src="@drawable/ic_launcher"

14.         />

15.     

16.     <TextView

17.         android:id="@+id/tv_address"

18.         android:layout_width="wrap_content"

19.         android:layout_height="wrap_content"

20.         />

21.     <TextView

22.         android:id="@+id/tv_age"

23.         android:layout_width="wrap_content"

24.         android:layout_height="wrap_content"

25.         />

26.     <TextView

27.         android:id="@+id/tv_name"

28.         android:layout_width="wrap_content"

29.         android:layout_height="wrap_content"

30.         />

31.     <TextView

32.         android:id="@+id/tv_phone"

33.         android:layout_width="wrap_content"

34.         android:layout_height="wrap_content"

35.         />

36. </LinearLayout>

                (2)根据JSON的数据结构构建实体类

1.  package com.qf.bean;

2.   

3.  public class Girl {

4.         private String address;

5.         private int age;

6.         private String avatar;

7.         private String name;

8.         private String phone;

9.        

10.        public String getAddress() {

11.               return address;

12.        }

13.        public void setAddress(String address) {

14.               this.address = address;

15.        }

16.        public int getAge() {

17.               return age;

18.        }

19.        public void setAge(int age) {

20.               this.age = age;

21.        }

22.        public String getAvatar() {

23.               return avatar;

24.        }

25.        public void setAvatar(String avatar) {

26.               this.avatar = avatar;

27.        }

28.        public String getName() {

29.               return name;

30.        }

31.        public void setName(String name) {

32.               this.name = name;

33.        }

34.        public String getPhone() {

35.               return phone;

36.        }

37.        public void setPhone(String phone) {

38.               this.phone = phone;

39.        }

40.        @Override

41.        public String toString() {

42.               return "Girl [address=" + address + ", age=" + age + ", avatar="

43.                            + avatar + ", name=" + name + ", phone=" + phone + "]";

44.        }

45.       

46.       

47.  

48. }

                (3)创建BaseAdapter的子类,并实现相关方法

1.  package com.qf.adapter;

2.   

3.  import java.util.List;

4.   

5.  import com.qf.asy.ImgAsy;

6.  import com.qf.bean.Girl;

7.  import com.qf.day10demo02.R;

8.  import com.qf.util.Constant;

9.   

10. import android.content.Context;

11. import android.view.LayoutInflater;

12. import android.view.View;

13. import android.view.ViewGroup;

14. import android.widget.BaseAdapter;

15. import android.widget.ImageView;

16. import android.widget.TextView;

17.  

18. public class GirlAdapter extends BaseAdapter{

19.        private List<Girl> data;

20.        private Context context;

21.       

22.        public GirlAdapter(List<Girl> data, Context context) {

23.               super();

24.               this.data = data;

25.               this.context = context;

26.        }

27.  

28.        @Override

29.        public int getCount() {

30.               return data.size();

31.        }

32.  

33.        @Override

34.        public Object getItem(int position) {

35.               return data.get(position);

36.        }

37.  

38.        @Override

39.        public long getItemId(int position) {

40.               return position;

41.        }

42.  

43.        @Override

44.        public View getView(int position, View convertView, ViewGroup parent) {

45.               ViewHolder viewHolder = null;

46.               if (convertView == null) {

47.                     viewHolder = new ViewHolder();

48.                    

49.                     convertView = LayoutInflater.from(context).inflate(R.layout.item, null);

50.                     viewHolder.img = (ImageView) convertView.findViewById(R.id.img);

51.                     viewHolder.tv_address = (TextView) convertView.findViewById(R.id.tv_address);

52.                     viewHolder.tv_age = (TextView) convertView.findViewById(R.id.tv_age);

53.                     viewHolder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);

54.                     viewHolder.tv_phone = (TextView) convertView.findViewById(R.id.tv_phone);

55.                    

56.                     convertView.setTag(viewHolder);

57.               }else {

58.                     viewHolder = (ViewHolder) convertView.getTag();

59.               }

60.              

61.               Girl girl = data.get(position);

62.               //拿到图片的后半段地址

63.               String avatar = girl.getAvatar();

64.               viewHolder.img.setTag(Constant.BASE_URL + avatar);

65.               //下载图片地址

66.               new ImgAsy(viewHolder.img).execute(Constant.BASE_URL + avatar);

67.              

68.              

69.               viewHolder.tv_address.setText(girl.getAddress());

70.               viewHolder.tv_age.setText(girl.getAge() +"");

71.               viewHolder.tv_name.setText(girl.getName());

72.               viewHolder.tv_phone.setText(girl.getPhone());

73.              

74.               return convertView;

75.        }

76.       

77.        class ViewHolder{

78.               ImageView img;

79.               TextView tv_address,tv_age,tv_name,tv_phone;

80.              

81.        }

82.  

83. }

                (4)创建网络工具类

1.  package com.qf.util;

2.   

3.  import java.io.ByteArrayOutputStream;

4.  import java.io.IOException;

5.  import java.io.InputStream;

6.  import java.net.HttpURLConnection;

7.  import java.net.MalformedURLException;

8.  import java.net.URL;

9.   

10.  

11. public class NetworkUtil {

12.        public static byte[] getBytes(String path){

13.               InputStream is = null;

14.               ByteArrayOutputStream baos = null;

15.               try {

16.                     URL url = new URL(path);

17.                     HttpURLConnection connection = (HttpURLConnection) url.openConnection();

18.                     connection.setRequestMethod("GET");

19.                     connection.setConnectTimeout(3000);

20.                     if (200 == connection.getResponseCode()) {

21.                            is = connection.getInputStream();

22.                            baos = new ByteArrayOutputStream();

23.                            int len = 0;

24.                            byte[] buffer = new byte[1024];

25.                            while((len = is.read(buffer)) != -1){

26.                                   baos.write(buffer,0,len);

27.                            }

28.                            return baos.toByteArray();

29.                     }

30.                    

31.               } catch (MalformedURLException e) {

32.                     e.printStackTrace();

33.               } catch (IOException e) {

34.                     e.printStackTrace();

35.               }finally{

36.                     if (is != null) {

37.                            try {

38.                                   is.close();

39.                            } catch (IOException e) {

40.                                   e.printStackTrace();

41.                            }

42.                     }

43.                    

44.                     if(baos != null){

45.                            try {

46.                                   baos.close();

47.                            } catch (IOException e) {

48.                                   e.printStackTrace();

49.                            }

50.                     }

51.               }

52.              

53.               return null;

54.              

55.        }

56. }

                (5)创建AsyncTask的子类并实现网络请求和JSON解析的功能

1.  package com.qf.asy;

2.   

3.  import java.util.ArrayList;

4.  import java.util.List;

5.   

6.  import org.json.JSONArray;

7.  import org.json.JSONException;

8.  import org.json.JSONObject;

9.   

10. import com.qf.bean.Girl;

11. import com.qf.util.NetworkUtil;

12.  

13. import android.content.Context;

14. import android.os.AsyncTask;

15. import android.widget.Toast;

16.  

17. public class DataAsy extends AsyncTask<String, Void, List<Girl>>{

18.        private DataCallback callback;

19.        private Context context;

20.       

21.        public DataAsy(DataCallback callback, Context context) {

22.               super();

23.               this.callback = callback;

24.               this.context = context;

25.        }

26.  

27.        @Override

28.        protected List<Girl> doInBackground(String... params) {

29.               byte[] bytes = NetworkUtil.getBytes(params[0]);

30.               if (bytes != null) {

31.                     String content = new String(bytes);

32.                     //Log.i("info", "=====content===="+content);

33.                     try {

34.                            JSONObject object = new JSONObject(content);

35.                            JSONArray array = object.optJSONArray("girls");

36.                            List<Girl> girlList = new ArrayList<Girl>();

37.                            Girl girl = null;

38.                            //optxxx:当key值不存在的时候,程序不会崩,而是获取一个类型的默认值

39.                            for (int i = 0; i < array.length(); i++) {

40.                                   JSONObject object2 = array.optJSONObject(i);

41.                                   girl = new Girl();

42.                                   girl.setAddress(object2.optString("address"));

43.                                   girl.setAge(object2.optInt("age"));

44.                                   girl.setAvatar(object2.optString("avatar"));

45.                                   girl.setName(object2.optString("name"));

46.                                   girl.setPhone(object2.optString("phone"));

47.                                  

48.                                   girlList.add(girl);

49.                                  

50.                            }

51.                           

52.                            return girlList;

53.                           

54.                     } catch (JSONException e) {

55.                            e.printStackTrace();

56.                     }

57.               }

58.              

59.               return null;

60.        }

61.  

62.        @Override

63.        protected void onPostExecute(List<Girl> result) {

64.               super.onPostExecute(result);

65.               if (result == null) {

66.                     Toast.makeText(context, "downLoad failed", Toast.LENGTH_LONG).show();

67.               }else {

68.                     callback.doResult(result);

69.               }

70.              

71.        }

72.       

73.       

74.        //声明一个接口

75.        public interface DataCallback{

76.               public void doResult(List<Girl> result);

77.        }

78.       

79. }

                (6)6、将解析的数据传入到自定义BaseAdapter适配器,并显示到ListView

1.  package com.qf.day10demo02;

2.   

3.  import java.util.ArrayList;

4.  import java.util.List;

5.   

6.  import com.qf.adapter.GirlAdapter;

7.  import com.qf.asy.DataAsy;

8.  import com.qf.asy.DataAsy.DataCallback;

9.  import com.qf.bean.Girl;

10. import com.qf.util.Constant;

11.  

12. import android.app.Activity;

13. import android.os.Bundle;

14. import android.view.View;

15. import android.view.View.OnClickListener;

16. import android.widget.AbsListView;

17. import android.widget.AbsListView.OnScrollListener;

18. import android.widget.Button;

19. import android.widget.ListView;

20.  

21.  

22. public class MainActivity extends Activity

23.             implements OnScrollListener,OnClickListener{

24.        private ListView listView;

25.        private Button btn_more;

26.        private GirlAdapter adapter;

27.        private List<Girl> totaList = new ArrayList<Girl>();

28.        private int page = 0;

29.       

30.     @Override

31.     protected void onCreate(Bundle savedInstanceState) {

32.         super.onCreate(savedInstanceState);

33.         setContentView(R.layout.activity_main);

34.         listView = (ListView) findViewById(R.id.listView);

35.         btn_more = (Button) findViewById(R.id.btn_more);

36.         listView.setOnScrollListener(this);

37.         btn_more.setOnClickListener(this);

38.         

39.         getData();

40.         adapter = new GirlAdapter(totaList, this);//空数据源

41.         listView.setAdapter(adapter);

42.         

43.         

44.         

45.       

46.     }

47.     

48.     private void getData(){

49.          new DataAsy(new DataCallback() {

50.                     @Override

51.                     public void doResult(List<Girl> result) {

52.                            totaList.addAll(result);

53.                            adapter.notifyDataSetChanged();

54.                           

55.                     }

56.               },this).execute(Constant.INDEX_PATH+page);

57.     }

58.  

59.        @Override

60.        public void onScrollStateChanged(AbsListView view, int scrollState) {

61.        }

62.        @Override

63.        public void onScroll(AbsListView view, int firstVisibleItem,

64.                     int visibleItemCount, int totalItemCount) {

65.               if (firstVisibleItem + visibleItemCount == totalItemCount) {

66.                     btn_more.setVisibility(View.VISIBLE);

67.               }else {

68.                     btn_more.setVisibility(View.GONE);

69.               }

70.              

71.        }

72.  

73.        @Override

74.        public void onClick(View v) {

75.               page++;

76.               getData();

77.              

78.        }

79.  

80.     

81. }

        <2>需要的核心类

                (1)BaseAdapter

                (2)AsyncTask

                (4)HttpClient

                (5)JSONObject/JSONArray

6、listview其他方法

        <1>listView.addHeaderView(view);

1.  View headView = LayoutInflater.from(this).inflate(R.layout.headlayout, null);

2.  //添加一个头部布局/控件,要在绑定适配器之前。

3.  listView.addHeaderView(headView);

        <2>listView.addFooterView(button);

1.  Button button = new Button(this);

2.  button.setText("底部按钮");

3.  //添加一个底部布局/控件

4.  listView.addFooterView(button);

        <3>listView.setEmptyView(emptyView);

1.  TextView emptyView = (TextView) findViewById(R.id.emptyView);

2.  //使用前提:emptyView必须是预先存在当前布局里面,隐藏的

3.  listView.setEmptyView(emptyView);

原文链接:http://www.apkbus.com/blog-815579-61200.html

0人推荐
随时随地看视频
慕课网APP