概要
这节课我们讲了ListView
自定义Adapter的方法,只要继承BaseAdapter
实现我们自己的类就可以了。我们还讲了使用HTTP协议连接网络的方法,用HttpURLConnection
即可。下面就给大家说说它们的详细用法。
BaseAdapter的使用方法
在上节课中,我们学到了ArrayAdapter
和SimpleAdapter
,但是这两个Adapter不够灵活,前者只能改变item中的一条文字,后者则能改变item中的多个图片,多条文字。但是这样的功能还是太简单,好多情况并不能满足我们的需求。比如,我们要实现一个列表,每行之间的背景色都不同,这样的需求虽然简单,但是使用上述的两个Adapter,我们却并不能很好的实现。
这时候,BaseAdapter
就登场了。从名字可以看出,他是一个基本的Adapter,里面关于显示item的东西都要我们自己实现。使用BaseAdapter
大致需要如下几步
- 创建一个类,并继承BaseAdapter
创建完,我们会发现,竟然出现错误了,怎么回事?因为BaseAdapter
实现了Adapter
接口,所以我们要实现接口定义的方法。在红线上按Alt+Enter,选择Implement Methods,全选所有方法,按OK即可。 - 几个重写的方法的介绍
-
public int getCount()
返回数据的个数,或者说ListView
中,item的个数。通常写return list.size();
-
public Object getItem(int position)
返回item所对应的数据,通常写return list.get(position);
-
public long getItemId(int position)
返回item对用的id,通常写return position;
-
public View getView(int position, View convertView, ViewGroup parent)
这个是我们最关注的方法,在这里我们返回ListView
中每个item对应的View
。
- 通常需要设置的类内变量
不知道大家发现没有,我们自定义的Adapter并没有数据源,这怎么办呢,当然是给它当变量传进来啊。
不过,还有一个问题需要解决,在getView()
方法中,我们怎么返回View呢,我们只是创建了item对应的布局(layout)啊。这时候,LayoutInflater
这个类就出场了,它可以将我们的布局文件(xxx.xml)转换成对应的View
。这么说,大家可能不太理解,大家可以回忆一下,我们创建的Activity
是怎样显示的布局文件呢。有人可能会说了,我怎么知道,我根本没关过它,它自己就显示出来了。其实因为我们新建工程时,Android Studio已经给我们生成好代码了,那就是在onCreate()
函数中的setContentView(R.layout.activity_main)
方法,其实它的内部就是使用LayoutInflater
,把我们的布局文件,转化成对应的View
并显示出来的。那么具体怎么用呢,我们使用这句话就好了。
View view = LayoutInflater.from(context).inflate(R.layout.xxx, null);
我们可以看出,在自定义的Adapter中,并没有Context
对象,所以我们也把它当参数传进来就哦了。那个null是什么呢,那个参数要为返回的view指定一个父布局Parent View。我们不用管它,传null
就好了。
- 具体演示
引用一句比较火的话
Talk is cheap. Show me the code
布局文件item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:id="@+id/iv"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/head1" />
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="周杰伦"
android:textSize="20sp" />
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="龙卷风"
android:textSize="20sp" />
</LinearLayout>
布局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.sunny.muke_scrollview1.MainActivity">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
实体类Song.java,可以理解为存放歌曲信息的数据结构
package com.sunny.muke_scrollview1;
/**
* 歌曲实体类
* Created by Sunny An on 2016/5/29.
*/
public class Song {
//歌曲名
private String songName;
//歌手名
private String singer;
//图片
private int picture;
public String getSongName() {
return songName;
}
public void setSongName(String songName) {
this.songName = songName;
}
public String getSinger() {
return singer;
}
public void setSinger(String singer) {
this.singer = singer;
}
public int getPicture() {
return picture;
}
public void setPicture(int picture) {
this.picture = picture;
}
}
自定义的适配器CustomAdapter.java
package com.sunny.muke_scrollview1;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
* 自定义Adapter
* Created by Sunny An on 2016/5/29.
*/
public class CustomAdapter extends BaseAdapter {
private List<Song> data;
private Context context;
private LayoutInflater inflater;
public CustomAdapter(List<Song> data, Context context) {
this.data = data;
this.context = context;
inflater = LayoutInflater.from(this.context);
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//将布局文件转化成View
View view = inflater.inflate(R.layout.item, null);
//找控件
TextView tvSongName = (TextView) view.findViewById(R.id.tv1);
TextView tvSinger = (TextView) view.findViewById(R.id.tv2);
ImageView ivPic = (ImageView) view.findViewById(R.id.iv);
//设置数据
Song song = data.get(position);
tvSongName.setText(song.getSongName());
tvSinger.setText(song.getSinger());
ivPic.setBackgroundResource(song.getPicture());
//设置背景
if (position % 2 == 0) {
view.setBackgroundColor(Color.LTGRAY);
} else {
view.setBackgroundColor(Color.DKGRAY);
}
return view;
}
}
在MainActivity.java中的初始化代码
List<Song> data = new ArrayList<>();
for (int i = 0; i < 100; i++) {
Song song = new Song();
song.setSinger("歌手" + i);
song.setSongName("歌曲" + i);
if (i % 2 == 0) {
song.setPicture(R.drawable.head1);
} else {
song.setPicture(R.drawable.head2);
}
data.add(song);
}
ListView listView = (ListView) findViewById(R.id.listView);
CustomAdapter adapter = new CustomAdapter(data, MainActivity.this);
listView.setAdapter(adapter);
- 最终效果
效果图
实现了,有木有。但是,这个LIstView
在性能上来说,并不是最优的,更好的使用方法,请参见文末的链接。
HttpURLConnection的使用方法
这个我就不说太多了,都是Java的知识,大家看看书,或者看文末链接吧,我就把代码贴出来了。需要注意的是,要在AndroidManifest.xml中加入网络权限,否则应用不能联网。同时,使用HttpURLConnection
访问网络的操作不能放到UI线程中,请创建非UI线程。
<uses-permission android:name="android.permission.INTERNET" />
使用GET方式访问百度页面
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL("https://m.baidu.com/");
//返回值是URLConnection,我们要做一次强制转换
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//设置连接超时时间5秒
connection.setConnectTimeout(5 * 1000);
//设置请求方式为GET
connection.setRequestMethod("GET");
//包装输入流
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
//获取所有文本
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
//把他打印出来
Log.v("result",sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
运行结果
补充链接
Java中entity(实体类)的写法规范
BaseAdapter的逗逼、普通、文艺写法
LayoutInflater的获取与使用
Java Thread 总结
HTTP协议的介绍
HttpURLConnection在 Java 帮助文档 中的介绍
Java输入输出流
网友评论