您的位置:首页 > 移动开发 > Android开发

Android listview加载不同布局与adapter用法

2016-06-10 20:03 567 查看
Android listview加载不同布局与adapter用法

android开发过程中会经常用到listview,虽然recycleview也出来了,但是还是存在一些bug没有解决,还不是特别的成熟,那我们就来介绍一下listview的使用及其加载不同布局的item的一般写法。

首先我们listview需要加载不同的布局,首先我们需要些几个不同的布局(我写不同item的布局喜欢以inflate_功能_type_one来命名,大家可以根据自己的习惯,但是一定要有一个好的编程习惯哦!!!)

布局一:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/txt_inflat_type_one"
android:background="#44C494"
android:layout_width="match_parent"
android:layout_height="40dp">
</TextView>


布局二:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:background="#ffa07a"
android:layout_width="match_parent"
android:layout_height="40dp">

<TextView
android:id="@+id/txt_inflat_type_two"
android:layout_width="200dp"
android:layout_height="match_parent" />

<ImageView
android:id="@+id/img_inflat_type_two"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@null"
android:background="@mipmap/ic_launcher"/>

</LinearLayout>


布局三:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="40dp">

<TextView
android:id="@+id/txt_inflat_type_there_1"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<TextView
android:id="@+id/txt_inflat_type_there_2"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>

</LinearLayout>


接下来就是需要写的是MyAdapter了,我这里是继承BaseAdapter来写的,首先我们需要重写BaseAdapter的四个方法,getCount(listview需要展示的个数,根据数据源而定的,我在这里是写的规固定的)、getItem(获取数据源的单个实体类)、getItemId(获取下角标位置)、getView(UI控件的获取及其数据的挂载)。

这里,我们需要写的是不同布局item显示的样式,我们还需要重写其他两个方法:getItemViewType(获取每一个下角标(position)相对应得item类型),getViewTypeCount(几种布局的显示的总数)。

注意

//listview显示时的不同布局的item
private int TypeOne=0;//注意这个不同布局的类型起始值必须从0开始
private int TypeTwo=1;
private int TypeThere=2;


因为在实际开发项目中,我们要加载的数据往往是特别大的,这时候我们就要考虑布局的复用,说到复用我们就要来了解一下ListView的原理:ListView中的每一个Item显示都需要Adapter调用一次getView的方法,这个方法会传入一个convertView的参数,返回的View就是这个Item显示的View。如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存,创建View对象(getLayoutInflater().inflate(R.layout.inflate_type_one, parent,false);从xml中生成View,这是属于IO操作)也是耗时操作,所以必将影响性能。Android提供了一个叫做Recycler(反复循环器)的构件,就是当ListView的Item从上方滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会从下方生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的Item的View,所以说如果能重用这个convertView,就会大大改善性能。

getView方法中的操作是这样的:先从xml中创建view对象(inflate操作,我们采用了重用convertView方法优化),然后在这个view去findViewById,找到每一个子View,如:一个TextView等。这里的findViewById操作是一个树查找过程,也是一个耗时的操作,所以这里也需要优化,就是使用viewHolder,把每一个子View都放在Holder中,当第一次创建convertView对象时,把这些子view找出来。然后用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。当第二次重用convertView时,只需从convertView中getTag取出来就可以。

我们就需要先写几个不同item需要的viewHolder类:

private class TypeOneViewHolder{
private TextView txt_inflat_type_one;
}

private class TypeTwoViewHolder{
private TextView txt_inflat_type_two;
private ImageView img_inflat_type_two;
}

private class TypeThereViewHolder{
private TextView txt_inflat_type_there_1;
private TextView txt_inflat_type_there_2;
}


getView方法:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

TypeOneViewHolder typeOneViewHolder = null;
TypeTwoViewHolder typeTwoViewHolder = null;
TypeThereViewHolder typeThereViewHolder = null;

int Type=getItemViewType(position);
//第一次没有加载convertView
if(convertView==null){
if(Type==TypeOne){
convertView=getLayoutInflater().inflate(R.layout.inflate_type_one,parent,false);
typeOneViewHolder=new TypeOneViewHolder();
typeOneViewHolder.txt_inflat_type_one= (TextView) convertView.findViewById(R.id.txt_inflat_type_one);
convertView.setTag(typeOneViewHolder);

}else if(Type==TypeTwo){
convertView=getLayoutInflater().inflate(R.layout.inflate_type_two,parent,false);
typeTwoViewHolder=new TypeTwoViewHolder();
typeTwoViewHolder.txt_inflat_type_two= (TextView) convertView.findViewById(R.id.txt_inflat_type_two);
typeTwoViewHolder.img_inflat_type_two= (ImageView) convertView.findViewById(R.id.img_inflat_type_two);
convertView.setTag(typeTwoViewHolder);
}else if(Type==TypeThere){
convertView=getLayoutInflater().inflate(R.layout.inflate_type_there,parent,false);
typeThereViewHolder=new TypeThereViewHolder();
typeThereViewHolder.txt_inflat_type_there_1= (TextView) convertView.findViewById(R.id.txt_inflat_type_there_1);
typeThereViewHolder.txt_inflat_type_there_2= (TextView) convertView.findViewById(R.id.txt_inflat_type_there_2);
convertView.setTag(typeThereViewHolder);
}

}else {
//布局的复用convertView
//根据setTag()和getTag()方法来实现布局的复用
if(Type==TypeOne){
typeOneViewHolder= (TypeOneViewHolder) convertView.getTag();
}else if(Type==TypeTwo){
typeTwoViewHolder= (TypeTwoViewHolder) convertView.getTag();
}else if(Type==TypeThere){
typeThereViewHolder= (TypeThereViewHolder) convertView.getTag();
}

}

//设置数据
if(Type==TypeOne){
typeOneViewHolder.txt_inflat_type_one.setText("第一种布局"+position);
}else if(Type==TypeTwo){
typeTwoViewHolder.txt_inflat_type_two.setText("第二种布局"+position);
typeTwoViewHolder.img_inflat_type_two.setImageResource(R.mipmap.ic_launcher);
}else if(Type==TypeThere){
typeThereViewHolder.txt_inflat_type_there_1.setText("第三种布局"+position+"左");
typeThereViewHolder.txt_inflat_type_there_2.setText("第三种布局"+position+"右");
}

return convertView;
}


实现效果截图:





最后附整体代码:

package com.example.administrator.baseadapterapplication;

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

/**
* Android listview加载不同布局与adapter用法
*@author wujun
*
*/

public class MainActivity extends AppCompatActivity {

private ListView listView;
private MyAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
}

private void initView() {
listView= (ListView) findViewById(R.id.listview);
}

private void initData() {
myAdapter=new MyAdapter(MainActivity.this);
listView.setAdapter(myAdapter);
myAdapter.notifyDataSetChanged();
}

//适配器
private class MyAdapter extends BaseAdapter {

private Context mcontext;

//listview显示时的不同布局的item
private int TypeOne=0;//注意这个不同布局的类型起始值必须从0开始
private int TypeTwo=1;
private int TypeThere=2;

private MyAdapter(Context context){
mcontext=context;
}

@Override
public int getCount() {
return 30;
}

@Override
public Object getItem(int position) {
return null;
}

@Override
public long getItemId(int position) {
return position;
}

//item的不同布局的判断
@Override
public int getItemViewType(int position) {
// return super.getItemViewType(position);
if(position==1||position==5||position==10||position==15||position==20||position==26){
return TypeOne;
}else if(position==2||position==6||position==8||position==13||position==23||position==0){
return TypeTwo;
}else {
return TypeThere;
}
}

@Override
public int getViewTypeCount() {
// return super.getViewTypeCount();
return 3;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

TypeOneViewHolder typeOneViewHolder = null;
TypeTwoViewHolder typeTwoViewHolder = null;
TypeThereViewHolder typeThereViewHolder = null;

int Type=getItemViewType(position);
if(convertView==null){
if(Type==TypeOne){
convertView=getLayoutInflater().inflate(R.layout.inflate_type_one,parent,false);
typeOneViewHolder=new TypeOneViewHolder();
typeOneViewHolder.txt_inflat_type_one= (TextView) convertView.findViewById(R.id.txt_inflat_type_one);
convertView.setTag(typeOneViewHolder);

}else if(Type==TypeTwo){
convertView=getLayoutInflater().inflate(R.layout.inflate_type_two,parent,false);
typeTwoViewHolder=new TypeTwoViewHolder();
typeTwoViewHolder.txt_inflat_type_two= (TextView) convertView.findViewById(R.id.txt_inflat_type_two);
typeTwoViewHolder.img_inflat_type_two= (ImageView) convertView.findViewById(R.id.img_inflat_type_two);
convertView.setTag(typeTwoViewHolder);
}else if(Type==TypeThere){
convertView=getLayoutInflater().inflate(R.layout.inflate_type_there,parent,false);
typeThereViewHolder=new TypeThereViewHolder();
typeThereViewHolder.txt_inflat_type_there_1= (TextView) convertView.findViewById(R.id.txt_inflat_type_there_1);
typeThereViewHolder.txt_inflat_type_there_2= (TextView) convertView.findViewById(R.id.txt_inflat_type_there_2);
convertView.setTag(typeThereViewHolder);
}

}else {

if(Type==TypeOne){
typeOneViewHolder= (TypeOneViewHolder) convertView.getTag();
}else if(Type==TypeTwo){
typeTwoViewHolder= (TypeTwoViewHolder) convertView.getTag();
}else if(Type==TypeThere){
typeThereViewHolder= (TypeThereViewHolder) convertView.getTag();
}

}

//设置数据
if(Type==TypeOne){
typeOneViewHolder.txt_inflat_type_one.setText("第一种布局"+position);
}else if(Type==TypeTwo){
typeTwoViewHolder.txt_inflat_type_two.setText("第二种布局"+position);
typeTwoViewHolder.img_inflat_type_two.setImageResource(R.mipmap.ic_launcher);
}else if(Type==TypeThere){
typeThereViewHolder.txt_inflat_type_there_1.setText("第三种布局"+position+"左");
typeThereViewHolder.txt_inflat_type_there_2.setText("第三种布局"+position+"右");
}

return convertView;
}

private class TypeOneViewHolder{ private TextView txt_inflat_type_one; } private class TypeTwoViewHolder{ private TextView txt_inflat_type_two; private ImageView img_inflat_type_two; } private class TypeThereViewHolder{ private TextView txt_inflat_type_there_1; private TextView txt_inflat_type_there_2; }

}

}


大家有什么android开发问题可以一起交流(QQ:965244491 附微信二维码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息