一.Listview和优化
首先
listview继承自AbsListView,(Gridview也继承自这个类,有机会再说),
(源码本人今天眼睛不舒服日后再看- -)
然后
关于Adapter。先说控件,是用来交互和展示数据的,但是由于listview需要展示的数据量过大,所以需要adapter提供数据,顾名思义,Adapter是适配器的意思,它在ListView和数据源之间起到了一个桥梁的作用,ListView并不会直接和数据源打交道,而是会借助Adapter这个桥梁来去访问真正的数据源,与之前不同的是,Adapter的接口都是统一的,因此ListView不用再去担心任何适配方面的问题。而Adapter又是一个接口(interface),它可以去实现各种各样的子类,每个子类都能通过自己的逻辑来去完成特定的功能,以及与特定数据源的适配操作。而adapter作为复杂数据的展示的转换载体,所以各种Adapter只不过是转换的方式和能力不一样而已。如图:
ArrayAdapter
ArrayAdapter是一个绑定View到一组对象的通用类。默认情况下,ArrayAdapter绑定每个对象的toString值到在layout中预先定义的TextView控件上。可变通的,构造函数允许你使用更加复杂的layout或者通过重写getView方法来扩展类从而使用TextView的替代物(如ImageView或嵌套的layout)。
SimpleCursorAdapter
SimpleCursorAdapter绑定View到Content Provider查询返回的游标上。指定一个XML layout定义,然后将数据集中的每一列的值绑定到layout中的一个View上。
Adapter的getView方法
个人觉得这个方法在重写adapter的时候上镜率很高,所以具体分析下。
public View getView(int position, View convertView, ViewGroup parent) {}
getview方法用来刷新listview,在每一次item从屏幕外滑进屏幕内的时候,或者程序刚开始的时候创建第一屏item的时候都会调用这个方法。
position是指当前dataset的位置,通过getCount和getItem来使用。如果list向下滑动的话那么就是最低端的item的位置,如果是向上滑动的话那就是最上端的item的位置。convertView是指可以重用的视图,即刚刚出队的视图。parent应该就是list。还有一个return:
A View corresponding to the data at the specified position.
具体使用看情况,完毕。
最后
关于listview的优化问题。菜鸟写法:
public class CustomAdapter extends ArrayAdapter {
private int dataid;
public CustomAdapter(@NonNull Context context, @LayoutRes int resource, @IdRes int textViewResourceId) {
super(context, resource, textViewResourceId);
dataid=resource;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view= LayoutInflater.from(getContext()).inflate(dataid,parent,false);
TextView textView=(TextView)view.findViewById(...);
ImageView imageView=(ImageView)view.findViewById(...);
return view;
}
}
上述方法效率低在:getview方法中每次都把布局重新加载了一遍。而且可以看到上述方法中有个convertview一直闲着,他是用来把之前加载好的布局先进行缓存,以便之后重用。所以优化getview如下:
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view;
if(convertView==null){
view= LayoutInflater.from(getContext()).inflate(dataid,parent,false);
}else{
view=convertView;
}
TextView textView=(TextView)view.findViewById(...);
ImageView imageView=(ImageView)view.findViewById(...);
return view;
}
上面这个方法虽然不会在重复加载布局,但是有一个叫做findviewbyid的方法一直重复使用。这个方法会自上而下的遍历控件树,十分消耗内存,所以再借助一个viewholder来优化性能。viewholder类需要自己进行定义(内部类):
class ViewHolder{
private Textview textview;
private Imageview imageview;
}
具体如下:
public view getView(int position,View convertview,ViewGroup parent){
View view;
ViewHolder viewholder;
if(convertview== null){
view=LayoutInflater.from(getContext()).inflate(dataid,parent,false);
viewholder = new ViewHolder();
viewholder.textview=(Textview)view.findviewbyId(...);
viewholder.imageview=(Imageview)view.findviewbyId(...);
view.setTag(viewholder); //将viewholder存储在view中
}else{
view = convertview;
viewholder= (ViewHolder)view.getTag(); //重新获取ViewHolder
}
return view;
}
view的setTag和getTag方法,存储和获取ViewHolder,不用每次重新加载都去调用findviewbyid方法。后续关于listiew的运用有缘再更新,接下来学习recyclerview.
二.Recyclerview
首先
recyclerview定义在了support库中,想用的话要先在build.gradle中添加依赖库。
dependencies{
...
compile 'com.android.support:recyclerview-v7:25.2.1'
...
}
然后
关于使用。基本和listview差不多,找几个方法说一哈:
- ItemDecoration:添加item之间的分割线。
addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));
也可以自己在style和drawable中定义分割线的颜色,这里先过。 - LayoutManager :这是一个抽象类,系统提供了3个实现类:
1 LinearLayoutManager 现行管理器,支持横向、纵向。
2 GridLayoutManager 网格布局管理器。
3 StaggeredGridLayoutManager 瀑布就式布局管理器。 - ItemAnimator: 设置item动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());有机会用到再详细学习。
最后
在下学习的是第二行代码里面有详细介绍了横向滚动和瀑布式布局,在此整理下。
- 横向布局就是利用了LinearLayoutManager实现:
LinearLayoutManager llm=new LinearLayoutManager(this);
llm.setorientation(LinearLayoutManager.HORIZONTAL);
recycleview.setLayoutManager(llm);
- StaggeredGridLayoutManager 瀑布就式布局管理器:
StaggeredGridLayoutManager mmm=new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
...
书中运用了一个Random方法看上去效果很明显这里就不赘述了。
最后
关于瀑布式布局的点击事件,重写了Adapter extends RecycleView.Adapter<...ViewHolder>,在ViewHolder中添加view的变量保存最外层布局实例,然后在onCreatedViewHolder()方法中添加点击时间就好了。具体项目以后做到再单独贴,书上的就不办过来了。
补充:
Recyclerview实际上是一个自定义的Viewgroup,子视图chilid对应着每一个RecyclerView的item。其中关于ItemDecoration类,可以优化它的视觉效果,具体的明天看心情写。
关于Recyclerview的界面跳转:
- 由于Recyclerview是没有onclicklistener的,所以跳转的时候写在了adapter的onCreateViewHolder中,本人用的是intent的隐式:
<activity android:name=".SecondActivity"
android:theme="@style/AppTheme.Zero">
<intent-filter>
<action android:name="android.intent.action.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent,int viewtype){
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.car_item,parent,false);
final ViewHolder viewHolder=new ViewHolder(view);
viewHolder.carview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position=viewHolder.getAdapterPosition();
Car car=mcarList.get(position);
Toast.makeText(view.getContext(),"你点击了"+car.getCarname()
,Toast.LENGTH_SHORT).show();
Intent intent=new Intent("android.intent.action.ACTION_START");
view.getContext().startActivity(intent);
}
});
因为心情原因就不多说了直接看代码。