如果小伙伴对AsyncTask没有了解的话,可以先参考下基础学习一
先上效果图
从慕课网上的服务器获取我们想要的消息列表(里面的控件有三个:一个图像、一个标题、一个详情内容)
MainActivity.java
写代码的思路:
(温馨提醒:NewsBean是一个类)
- 先写布局文件(只有一个ListView)
- 声明变量绑定控件
- 创建内部类AsyncTask
- AsyncTask中的execute()调用在四个方法之前
- 在doInBackground()执行耗时任务
写构造方法getJsonData(): 先打开流readStream();再用JOSNObject 对json数据进行解析; - 在onPostExecute()将结果展示在界面上
这里需要用到适配器
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:padding="16dp">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lv_main"></ListView>
</RelativeLayout>
public class MainActivity extends AppCompatActivity {
ListView mListView;
private static String url="http://www.imooc.com/api/teacher?type=4&num=30";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView=findViewById(R.id.lv_main);
NewsAsyncTask task = new NewsAsyncTask();
task.execute(url);
}
//String:初始传入的url
//Void:没有过程
//List<NewsBean>: 最后获取到的结果是一个集合
class NewsAsyncTask extends AsyncTask<String ,Void,List<NewsBean>>{
@Override
protected List<NewsBean> doInBackground(String... params) {
//params[0]从第一个访问
return getJsonData(params[0]);
}
@Override
protected void onPostExecute(List<NewsBean> newsBeans) {
super.onPostExecute(newsBeans);
//doInBackground()获取的数据,加载到ListView中,必须要有中介质
//适配器必须要有布局文件和数据匹配
NewsAdapter adapter = new NewsAdapter(newsBeans,MainActivity.this);
mListView.setAdapter(adapter);
}
}
//先获取到网页服务的json数据,然后进行json数据进行解析
private List<NewsBean> getJsonData(String url){
List<NewsBean> newsBeanList = new ArrayList<>();
String jsonString = null;
try {
//打开字节流,重写readStream方法
jsonString = readStream(new URL(url).openStream());
Log.d("data",jsonString);
//网页获取到的数据为json数据
//将json数据解析,把数据绑定到对应的控件
JSONObject jsonObject;
NewsBean newsBean;
//1、new jsonObject()对象
//2.用getJsonXX()获取
jsonObject = new JSONObject(jsonString);
//通过获取到的数据可知,json是一个数组属性(获取到我们需要的数组)
JSONArray jsonArray = jsonObject.getJSONArray("data");
//遍历循环数组,最后将数组存入集合
for (int i = 0; i<jsonArray.length();i++){
jsonObject=jsonArray.getJSONObject(i);
newsBean = new NewsBean();
newsBean.newsIconUrl=jsonObject.getString("picSmall");
newsBean.newsTitle=jsonObject.getString("name");
newsBean.newsDescribe=jsonObject.getString("description");
newsBeanList.add(newsBean);
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return newsBeanList;
}
/**
* 打开流
* 1、将字节流转化成字符流
* 2、将字符流存入缓冲区
* 3、从缓冲区中一行一行地读取数据
* ***/
private String readStream(InputStream is){
InputStreamReader isr;
String line="";
String result="";
try {
//将字节流转换成字符流
isr = new InputStreamReader(is,"utf-8");
BufferedReader br = new BufferedReader(isr);
//在缓冲容器里获取到数据追加到result
while((line=br.readLine())!=null){
result+=line;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
构建实例类NewsBean
作用:负责适配器跟主类的连接
public class NewsBean {
public String newsIconUrl;
public String newsTitle;
public String newsDescribe;
}
构建适配器NewsAdapter.java
(温馨提醒:ImageLoadAsyncTask是一个类)
写代码的思路:
我们需要完成两个东西:
- 完成条目布局文件并且加载到视图上
- 将获取到的数据跟组件绑定
<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="4dp">
<ImageView
android:layout_width="64dp"
android:layout_height="64dp"
android:id="@+id/iv_icon"
android:src="@mipmap/ic_launcher"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:paddingLeft="4dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tv_title"
android:textSize="15sp"
android:maxLines="1"
android:text="Title"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tv_content"
android:text="Content"
android:maxLines="3"
android:textSize="10sp"/>
</LinearLayout>
/要布局文件,而且还有数据
public class NewsAdapter extends BaseAdapter {
private List<NewsBean> mList;
private LayoutInflater inflater;
/**
* 调用LayoutInflater有三种方法
* 1、LayoutInflater=getLayoutInflater();//调用Activity的getLayoutInflater;
* 2、LayoutInflater inflater = LayoutInflater.from(context);
* 3.LayoutInflater inflater = (LayoutInflater) context.getSystemService;
* **/
public NewsAdapter(List<NewsBean> mList, Context context) {
this.mList = mList;
this.inflater = LayoutInflater.from(context);
}
//获取List列表中有多少个对象
@Override
public int getCount() {
return mList.size();
}
//获取列表中的具体位置
@Override
public Object getItem(int i) {
return mList.get(i);
}
//获取单独的Item对象的ID
@Override
public long getItemId(int i) {
return i;
}
//1、加载布局文件;2、定义变量;3、绑定控件;4、设置数据到空间上
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder= null;
if (view==null){
viewHolder=new ViewHolder();
//加载布局文件放到视图中去
view=inflater.inflate(R.layout.item_layout,null);
//绑定控件
viewHolder.ivIcon=view.findViewById(R.id.iv_icon);
viewHolder.tvTitle=view.findViewById(R.id.tv_title);
viewHolder.tvContent=view.findViewById(R.id.tv_content);
view.setTag(viewHolder);
}else {
viewHolder= (ViewHolder) view.getTag();
}
//将数据放入控件中
//将网络上的照片通过URL地址传入到ImageView中
String url = mList.get(i).newsIconUrl; //先获取对应图片的地址
viewHolder.ivIcon.setTag(url); //因为我们只有图像地址,所以找一个容器setTag()来装
new ImageLoadAsyncTask().showImageViewByAsyncTask(viewHolder.ivIcon,url);
viewHolder.tvTitle.setText(mList.get(i).newsTitle);
viewHolder.tvContent.setText(mList.get(i).newsDescribe);
return view;
}
//ViewHolder通常出现在适配器里,为的是listview滚动的时候快速设置值,而不必每次都重新创建很多对象,从而提升性能。
class ViewHolder{
public TextView tvTitle,tvContent;
public ImageView ivIcon;
}
}
ImageLoadAsyncTask.java
在MainActivity.java中,打印在日志文件json数据通过解析之后可发现,图片的来源是链接,所以我们又需要进一步异步获取图片。(这里的json数据可以通过百度搜索“json解析工具”进行查看)
写代码思路:
一句话总结这里的篇代码:“一个方法:显示图片,传递参数 。一个类:异步消息下载图片”。
public class ImageLoadAsyncTask {
public void showImageViewByAsyncTask(ImageView imageView,String url){
new NewsAsyncTask(imageView,url).execute(url);
}
private class NewsAsyncTask extends AsyncTask<String,Void, Bitmap>{
//先声明变量再实例化 : 传入String url ,返回图像Bitmap
private ImageView imageView;
private String url;
public NewsAsyncTask(ImageView imageView,String url) {
this.imageView=imageView;
this.url=url;
}
@Override
protected Bitmap doInBackground(String... params) {
//从第0个获取
return getBitmapFromUrl(params[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
//判断控件绑定的数据是否跟获取到的数据相等,如果相同将位图绑定到控件上
if (imageView.getTag().equals(url)){
imageView.setImageBitmap(bitmap);
}
}
public Bitmap getBitmapFromUrl(String urlString){
Bitmap bitmap = null;
InputStream is = null;
try {
URL url = new URL(urlString);
try {
//打开连接(http)
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//转换为字节流
is = new BufferedInputStream(connection.getInputStream());
//解码字节流
bitmap=BitmapFactory.decodeStream(is);
connection.disconnect();
//最后返回结果
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
//当出现报错时,最后返回一个空值
return null;
}
}
}
最后别忘记添加网络权限了哦
<uses-permission android:name="android.permission.INTERNET"/>
如果对您有帮助,麻烦您点一个小赞给博主。谢谢~