今天学习了Listview的相关内容,通过查找最佳方法来实现listview的效果,最后,发现listview常用的有三种途径,以BaseAdapter适配类为例,它们主要区别在于getview()方法中使用的区别:
1).getview()中的view不经过任何处理,最后返回的是view型。如果列表数据量比较大,这种方法每次会重新创建view,配置资源,严重影响性能
2).geteview()中使用convertview来缓存,这种缓存convertview的方式可以判断缓存中是否存在view,如果不存在则创建,,如果存在就直接调用缓存中的view,提高了性能
3).getview()中使用convertview和ViewHolder来实现。ViewHolder不是Android的开发API,而是一种设计方法,就是创建一个类来缓存view,进一步加快了ui的响应速度。
所以,我才用的是第三种方法实现。下面来看下实现方法:
1.首先创建的布局文件activity_main.xml,里面只有一个listview,再创建一个其item的子布局文件listview_item.xml,直接上item布局代码:
xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:id="@+id/list_item_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical"> <ImageView android:id="@+id/img" android:layout_width="50dp" android:layout_height="50dp" android:src="@mipmap/icon_withdraw_id_card" android:layout_marginLeft="12dp" android:layout_marginRight="12dp"/> <LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="8dp"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="像风一样" android:textSize="22sp" /> <TextView android:id="@+id/message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="今天有空吗?我们一起去游玩吧" android:textSize="16sp" /> LinearLayout> LinearLayout>item布局中包含一个imageview,两个textview。
2.创建用户的数据信息类,便于对控件的内容进行操作
package com.example.administrator.applist; /** * Created by Administrator on 2017/3/6. * 用户的数据类 */ public class UserInfo { private String imageUrl; private String name; private String message; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getImageUrl() { return imageUrl; } public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
3.创建ViewHolder类,为view缓存
package com.example.administrator.applist; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; /** * Created by Administrator on 2017/3/6. */ /* 使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。 */ class ViewHolder{ public ImageView img; public TextView name; public TextView message; public LinearLayout linearLayout; }
同时创建构造方法,方便传入数据
最主要的方法在于getview();首先判断一下缓存中是否为空,如果为空,通过ViewHolder来中缓存来创建view,避免了直接创建,影响响应效果;不为空就获取view。
代码中注释都比较详细,不需要再做说明,看了就懂。
package com.example.administrator.applist; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import java.util.ArrayList; /** * Created by Administrator on 2017/3/6. */ /* 实现listview的适配器,继承自Baseadapter */ class MyAdapter extends BaseAdapter { private ArrayList5.在activity中实现listview的适配和动态加载数据userInfos; private Context context; public MyAdapter(Context context,ArrayList userInfos){//构造方法 this.context=context; this.userInfos=userInfos; } @Override public int getCount() { return userInfos != null ? userInfos.size() : 0; } @Override public Object getItem(int position) { return userInfos.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder=null; if(convertView==null){//如果缓存convertView为空,则需要创建View viewHolder=new ViewHolder(); LayoutInflater mInflater = LayoutInflater.from(context); convertView = mInflater.inflate(R.layout.listview_item, null); //为自定义的item加载其中的布局 viewHolder.linearLayout= (LinearLayout) convertView.findViewById(R.id.list_item_layout); viewHolder.img= (ImageView) convertView.findViewById(R.id.img); viewHolder.name= (TextView) convertView.findViewById(R.id.name); viewHolder.message= (TextView) convertView.findViewById(R.id.message); //把item的布局保存到缓存器中,并将其用Tag标记,以便后面取出 convertView.setTag(viewHolder); }else{//否则将缓存中的布局取出 viewHolder= (ViewHolder) convertView.getTag(); } UserInfo user= (UserInfo) getItem(position); if (user!=null){//设置控件 viewHolder.img.setImageResource(R.mipmap.icon_withdraw_name); viewHolder.name.setText(user.getName()); viewHolder.message.setText(user.getMessage()); viewHolder.linearLayout.setBackgroundResource(R.drawable.item_shape); } return convertView; } }
大家可以先通过arraylist遍历加载数据,然后为listview适配。
package com.example.administrator.applist; import android.content.Context; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.ListView; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { private ListView listView; private ArrayList注意点:其中imageview是打算用imageloader动态加载图片的,所以定义的string类型,后来偷了懒,大家可以根据实际需要增加功能或者改成int型通过R.id.xx调用drawble中图片。userList; private Context mcontext;//上下文 //private MyAdapter myAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mcontext=MainActivity.this;//设置活动上下文 listView= (ListView) findViewById(R.id.list);//获取listview //myAdapter=new MyAdapter(mcontext,userList);//回写构造方法,将userlist传进去 //get data userList=new ArrayList () ; for (int i=0;i<30;i++){ UserInfo userInfo=new UserInfo(); userInfo.setImageUrl(" "); userInfo.setName("大雄"); userInfo.setMessage("今天天气不错,一起去爬山吧!"); userList.add(userInfo); listView.setAdapter(new MyAdapter(mcontext,userList)); } } }
简单效果图放一下:
功能比较简单,只是给自己提个醒,以后用这种优化方法使用listview。
6.遇到的问题:
1).Failed to get GED Log Buf, err(0)
2).java.lang.NoSuchMethodException: org.a
3).ERROR/InputDispatcher(206): channel '40f37a70 com
这一系列问题通过将MyAdapter和viewHolder类外置得到解决,最好不要作为内部类。
7.小结:
1 ).将使用到的适配类和工具类封装到外部,不要混放在activity中容易出错
2).listview数据的加载需要思考适合用哪种数据类型实现,,灵活一些
3).后期listview学习笔记(二)的改进:
.增加listview的item的响应事件操作
.思考如何为listview的item设置圆角来实现美感?
.listview与其他布局的组合使用来实现新效果
补充:本文纯手打,只用来记录日常学习过程和大家参考,不足之处希望大家指出并改正,谢谢。