Android中用面向对象思想实现AsyncTask类的复用

来源:互联网 发布:c语言int main 编辑:程序博客网 时间:2024/06/05 10:23

用过AsyncTask类去异步加载数据的同学一定清楚,当我们每写一个网络请求的时候都要新建一个类去继承AsyncTask类然后进行异步任务的操作。但是呢,每个网络请求都要写一个AsyncTask麻不麻烦?能不能只写一个AsyncTask实现所有的网络请求呢?答案是肯定的,要不然要面向对象是干嘛吃的啊!下面介绍如何实现AsyncTask类的复用问题。
老规矩,先来看效果图
这里写图片描述
这里写图片描述
两个页面的Item布局不相同,第一个页面Item有三个TextView,第二个页面的item有两个TextView,因此写的时候需要两个实体类去适配(实际上这两个页面布局基本一样完全可以只写一个,但本片文章为了讲解复用AsyncTask类,因此在这里写了两个实体。)
AsyncTask类的通常用法,下面截取上篇文章中的一段代码(非本程序中的代码)来分析。代码如下:

import java.util.List;import com.example.listview.adapter.MyAdapter;import com.example.listview.bean.PictureBean;import com.example.listview.utils.HttpUtils;import com.example.listview.utils.MyJsonUtils;import android.os.AsyncTask;public class MyAsyncTask extends AsyncTask<String, Void, byte[]> {    List<PictureBean> list;     MyAdapter adapter; //自定义Adapter    public MyAsyncTask(List<PictureBean> list, MyAdapter adapter) {        super();        this.list = list;        this.adapter = adapter;    }    @Override    protected byte[] doInBackground(String... params) {        return HttpUtils.getBytesByUrl(params[0]);    }    @Override    protected void onPostExecute(byte[] result) {        super.onPostExecute(result);        if(result!=null){            String jsonStr=new String(result,0,result.length);            System.out.print(jsonStr);            List<PictureBean> list2= (List<PictureBean>) MyJsonUtils.parseJson(jsonStr);            list.addAll(list2);            adapter.notifyDataSetChanged();        }    }}

上边的代码定义一个类MyAsyncTask继承AsyncTask。
AsyncTask是抽象类,该类定义了三种泛型类型 Params,Progress和Result。三种类型的作用如下:

  1. Params 启动任务执行的输入参数,比如HTTP请求的URL。该参数决定了 doInBackground方法中的参数类型。
  2. Progress 后台任何执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
  3. Result 当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。比如String,Integer等。该参数决定了doInBackground的返回值类型和onPostExecute方法中的参数类型。

接下来重点说下MyAsyncTask的构造方法,该方法中有两个参数,Adapter和List。在Activity中调用MyAsyncTask的构造方法时必须传入这两个参数,而对于不同的下载请求传入的参数会有可能不一致(比如List的泛型为不同的实体类),因此造成AsyncTask不能被复用,所以不得不为不同的请求写对应的AsyncTask类。但其实我们完全可以通过改变MyAsyncTask的构造方法的参数来实现MyAsyncTask类的复用。这就涉及到了java中的面向对象。即通过多态实现复用。
看修改后的AsyncTask类:

import java.util.List;import android.os.AsyncTask;import android.widget.BaseAdapter;import com.example.simly.asynctask.bean.Bean;import com.example.simly.asynctask.utils.HttpUtils;import com.example.simly.asynctask.utils.JsonUtils;/** * Created by zhpan on 2016/7/25. * 异步任务类,此类实现了复用功能 */public class MyAsyncTask extends AsyncTask<String, Void, byte[]> {    List<Bean> list;    BaseAdapter adapter;    JsonUtils utils;    public MyAsyncTask( List<? extends Bean> list,        BaseAdapter adapter,JsonUtils utils) {        super();        this.list = (List<Bean>) list;        this.adapter = adapter;        this.utils=utils;    }    @Override    protected byte[] doInBackground(String... params) {        return HttpUtils.getBytesByUrl(params[0]);    }    @Override    protected void onPostExecute(byte[] result) {        super.onPostExecute(result);        if(result!=null){            String jsonStr=new String(result,0,result.length);            System.out.print(jsonStr);            List<Bean> list2= (List<Bean>) utils.parseJson(jsonStr);            list.addAll(list2);            adapter.notifyDataSetChanged();        }    }}

上面代码中构造方法中的参数变成了三个,而且List的泛型做了修改,修改后的泛型为<? extends Bean>即该泛型可以接受所有继承Bean类的实体类,因此我定义了一个空接口Bean,接口Bean中没有任何代码。具体如下:

public interface Bean {}

接下来让所有实体类都去实现Bean接口

/** * Created by zhpan on 2016/7/25. */public class Bean1 implements Bean {    String title;    String doc_id;    String comments_num;    public Bean1() {    }    public String getTitle() {        return title;    }    public void setTitle(String title) {        this.title = title;    }    public String getDoc_id() {        return doc_id;    }    public void setDoc_id(String doc_id) {        this.doc_id = doc_id;    }    public String getComments_num() {        return comments_num;    }    public void setComments_num(String comments_num) {        this.comments_num = comments_num;    }    @Override    public String toString() {        return "Bean1{" +                "title='" + title + '\'' +                ", doc_id='" + doc_id + '\'' +                ", comments_num='" + comments_num + '\'' +                '}';    }}
/** * Created by zhpan on 2016/7/25. */public class Bean2 implements Bean {    String title;    String comments_num;    public Bean2() {    }    public String getTitle() {        return title;    }    public void setTitle(String title) {        this.title = title;    }    public String getComments_num() {        return comments_num;    }    public void setComments_num(String comments_num) {        this.comments_num = comments_num;    }    @Override    public String toString() {        return "Bean2{" +                "title='" + title + '\'' +                ", comments_num='" + comments_num + '\'' +                '}';    }}

这样写有什么作用?其实很容易发现通过这种方法我们在调用MyAsyncTask 类的构造方法时就可以传入所有List的泛型为实现了Bean接口的实体类,比如List<Bean1>、List<Bean2>都可以作为构造方法的参数。因为Bean1、Bean2有共同的父类Bean,Bean1、Bean2通过向上转型可以变成Bean,然后再MyAsyncTask 类中再通过向下转型为Bean1或Bean2。这样无论是什么样的实体类只要实现了Bean接口就可以传入MyAsyncTask 。
我们注意到MyAsyncTask 类的构造方法中还多了一个参数,该参数为JsonUtils utils。这是个什么方法呢?其实JsonUtils是一个解析Json的工具类,通过Json字符串解析出对应的实体对象并添加到集合,最后返回参数为解析出来的实体对象集合。可以看下边的代码(非本程序代码):

import java.util.ArrayList;import java.util.List;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;public class JsonUtils{    public static List<Bean1> parseJson(String jsonStr){        List<Bean1> list=new ArrayList<PictureBean>();        try {            JSONObject obj1=new JSONObject(jsonStr);            JSONArray array=obj1.getJSONArray("list");            for(int i=0;i<array.length();i++){                PictureBean per=new PictureBean();                JSONObject obj2=array.optJSONObject(i);                String title=obj2.optString("title");                String pic_url=obj2.optString("pic_url");                String web_url=obj2.optString("web_url");                per.setTitle(title);                per.setPic_url(pic_url);                per.setWeb_url(web_url);                list.add(per);            }        } catch (JSONException e) {            e.printStackTrace();        }        return list;    }}

但是如果这样写会不会有问题?很明显JsonUtils解析出来的结果只能对应一种实体类,如果只把JsonUtils作为MyAsyncTask类的构造方法的参数的话依然没办法实现MyAsyncTask类的复用!那么该怎么办呢?
其实思路还是跟上边一样的,我们不妨定义一个接口JsonUtils,接口中定义一个抽象方法 parseJson,parseJson的参数为String,返回值为List<? extends Bean>,即所有实现了Bean接口的实体类的集合。
代码如下:

import com.example.simly.asynctask.bean.Bean;import java.util.List;/** * Created by zhpan on 2016/7/25. */public interface JsonUtils {     List<? extends Bean> parseJson(String jsonStr);}

接下来让所有的解析jison的工具类都实现JsonUtils接口并重写parseJson方法。
解析Bean1的工具类如下:

import com.example.simly.asynctask.bean.Bean1;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import java.util.ArrayList;import java.util.List;/** * Created by zhpan on 2016/7/25. * 解析url1对应的json,将解析后的实体添加到集合并返回该集合 */public class Bean1JsonUtils implements JsonUtils {    Bean1 bean;    List<Bean1> list=new ArrayList<>();    @Override    public List<Bean1> parseJson(String jsonStr) {        try {            JSONObject obj1=new JSONObject(jsonStr);            JSONArray array=obj1.optJSONArray("list");            for(int i=0;i<array.length();i++){                bean=new Bean1();                JSONObject obj2=array.optJSONObject(i);                bean.setTitle(obj2.optString("title"));                bean.setComments_num(obj2.optString("comments_num"));                bean.setDoc_id(obj2.optString("doc_id"));                list.add(bean);            }        } catch (JSONException e) {            e.printStackTrace();        }        return list;    }}

解析Bean2的工具类如下:

/** * Created by zhpan on 2016/7/25. * 解析url2对应的json,将解析后的实体添加到集合并返回该集合 */public class Bean2JsonUtils implements JsonUtils {    Bean2 bean;    List<Bean2> list=new ArrayList<>();    @Override    public List<Bean2> parseJson(String jsonStr) {        try {            JSONObject obj1=new JSONObject(jsonStr);            JSONArray array=obj1.optJSONArray("list");            for(int i=0;i<array.length();i++){                bean=new Bean2();                JSONObject obj2=array.optJSONObject(i);                bean.setTitle(obj2.optString("title"));                bean.setComments_num(obj2.optString("comments_num"));                list.add(bean);            }        } catch (JSONException e) {            e.printStackTrace();        }        return list;    }}

至此AsyncTask类的复用已经完成,不管对于怎样的实体类,我们只要让其实现Bean接口,并让其Json解析的工具类实现JsonUtils接口并重写parseJson方法,在调用MyAsyncTask类的构造方法中就可以传入不同的实体类和不同的json解析工具类,从而实现了MyAsyncTask类的复用,这样大大的减少了程序的代码量。
来看下效果:
第一页(Fragment1),MyAsyncTask的构造方法中传入了实体Bean1的集合和解析Bean1的工具类Bean1JsonUtils(效果图见开篇图片1)。

import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ListView;import com.example.simly.asynctask.R;import com.example.simly.asynctask.adapter.Fragment1Adapter;import com.example.simly.asynctask.bean.Bean1;import com.example.simly.asynctask.constant.MyUrl;import com.example.simly.asynctask.utils.Bean1JsonUtils;import com.example.simly.asynctask.asynctask.MyAsyncTask;import java.util.ArrayList;import java.util.List;public class Fragment1 extends Fragment {    View mView;    ListView mListView;    List<Bean1> list;    @Override    public View onCreateView(LayoutInflater inflater,                             @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        mView = inflater.inflate(R.layout.fragment1, null);        //  1.初始化ListView        mListView= (ListView) mView.findViewById(R.id.lv_fragment1);        //  2.初始化List集合        list=new ArrayList<>();        //  3.创建适配器        Fragment1Adapter adapter=new Fragment1Adapter(getContext(),list);        //  4.为listview匹配适配器        mListView.setAdapter(adapter);        //  5.异步任务为List加载数据        new MyAsyncTask(list,adapter,new Bean1JsonUtils()).execute(MyUrl.url1);        return mView;    }}

第二页(Fragment2),MyAsyncTask的构造方法中传入了实体Bean2的集合和解析Bean2的工具类Bean2JsonUtils(效果图见开篇图片2)。

import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ListView;import com.example.simly.asynctask.R;import com.example.simly.asynctask.adapter.Fragment2Adapter;import com.example.simly.asynctask.bean.Bean2;import com.example.simly.asynctask.constant.MyUrl;import com.example.simly.asynctask.utils.Bean2JsonUtils;import com.example.simly.asynctask.asynctask.MyAsyncTask;import java.util.ArrayList;import java.util.List;public class Fragment2 extends Fragment{    View mView;    ListView mListView;    List<Bean2> list;    @Override    public View onCreateView(LayoutInflater inflater,            @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {         mView=inflater.inflate(R.layout.fragment2, null);        //  1.初始化ListView        mListView= (ListView) mView.findViewById(R.id.lv_fragment2);        //  2.初始化List集合        list=new ArrayList<>();        //  3.创建适配器        Fragment2Adapter adapter=new Fragment2Adapter(getContext(),list);        //  4.为listview匹配适配器        mListView.setAdapter(adapter);        //  5.异步任务为List加载数据        new MyAsyncTask(list,adapter,new Bean2JsonUtils()).execute(MyUrl.url2);        return mView;    }}

就此大功告成!
源码下载(Android Studio):http://download.csdn.net/detail/qq_20521573/9585874

0 0
原创粉丝点击