开源中国源码学习数据篇(一)之android-async-http框架和AsyncTask

来源:互联网 发布:白凡泄露天机知乎 编辑:程序博客网 时间:2024/06/05 09:45

    今天来进行数据(从开源中国服务器上面get新闻信息)的联网获取,关键步骤就是应用android-async-http框架,输入向服务器post的参数,异步获得服务器的数据。接着异步解析成adapter可以用的ListEntity<T>格式,在ListView中展示出来。

一、定义基类ListBaseAdapter文件

      核心数据是mDatas,后面的关键代码就是从服务器获取数据,并将XML异步解析,添加到mDatas中,最后在ListView中展示。获取服务器数据用到了android-async-http框架。这个ListBaseAdapter文件用于存放ListView数据适配的公共方法。

protected ArrayList<T> mDatas = new ArrayList<T>();@Override    public int getCount() {        return getDataSize();    }    @Override    public Object getItem(int pos) {        if(mDatas.size()>pos)            return mDatas.get(pos);        return null;    }    @SuppressWarnings("deprecation")    @SuppressLint("InflateParams")    @Override    public View getView(int pos, View convertView, ViewGroup parent) {         return getRealView(pos, convertView, parent);    }    public int getDataSize() {        return mDatas.size();    }    protected View getRealView(int position, View convertView, ViewGroup parent) {        return null;    }    public ArrayList<T> getData() {        return mDatas == null ? (mDatas = new ArrayList<T>()) : mDatas;    }//将转换的数据,添加到mDatas     public void addData(List<T> data) {            if (mDatas != null && data != null && !data.isEmpty()) {                mDatas.addAll(data);            }            notifyDataSetChanged();            Log.i("a", "ss");        }

二、展示新闻数据的适配文件-NewsAdapter

    继承于ListBaseAdapter,具体的对layout中的控件进行赋值。

 @SuppressLint("InflateParams")    @Override    protected View getRealView(int position, View convertView, ViewGroup parent) {        ViewHolder vh = null;        if (convertView == null || convertView.getTag() == null) {            convertView = getLayoutInflater(parent.getContext()).inflate(                    R.layout.list_cell_news, null);            vh = new ViewHolder(convertView);            convertView.setTag(vh);        } else {            vh = (ViewHolder) convertView.getTag();        }        News news = mDatas.get(position);        vh.title.setText(news.getTitle());        //给里面的各个控件赋值        ………………………………………………………}

三、Fragment类型文件的界面-BaseListFragment

1、概述

    显示数据的基类,最终展示界面NewsFragment的父类。
    BaseFragment为BaseListFragment的父类,供Fragment类继承,里面有一些用来复写的方法,比如onCreateView(),onViewCreated()等。
    下面为BaseListFragment文件的代码:
public abstract class BaseListFragment<T extends Entity> extends BaseFragment implements        OnItemClickListener, OnScrollListener,SwipeRefreshLayout.OnRefreshListener {    @InjectView(R.id.listview)    protected ListView mListView;        protected ListBaseAdapter<T> mAdapter;    protected abstract ListBaseAdapter<T> getListAdapter();    private ParserTask mParserTask;    @Override    public void onViewCreated(View view, Bundle savedInstanceState) {        super.onViewCreated(view, savedInstanceState);        ButterKnife.inject(this, view);        //初始化界面        initView(view);    }    @Override    public void initView(View view) {        mSwipeRefreshLayout.setOnRefreshListener(this);        mListView.setOnItemClickListener(this);        mListView.setOnScrollListener(this);        if (mAdapter != null) {            mListView.setAdapter(mAdapter);        } else {            //根据不同的list 不同子类有不同geiListAdapter的实现            mAdapter = getListAdapter();            mListView.setAdapter(mAdapter);                //获取数据地方                requestData(false);        }    }

2、定义handler处理服务器传回的数据

    接收请求结果,一般重写onSuccess及onFailure接收请求成功或失败的消息,还有onStart,onFinish等消息。当接收到服务器传来的信息后,如果成功调用 executeParserTask(responseBytes)方法。向服务器post数据的操作、android-async-http框架的使用在后面介绍,数据请求在NewsFragment文件中执行。

protected AsyncHttpResponseHandler mHandler = new AsyncHttpResponseHandler() {        @Override        public void onSuccess(int statusCode, Header[] headers,                byte[] responseBytes) {                executeParserTask(responseBytes);        }}private void executeParserTask(byte[] data) {        cancelParserTask();        mParserTask = new ParserTask(data);        mParserTask.execute();    }

3、继承于AsyncTask的异步解析任务-ParserTask

  AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.
        至少要复用两个方法,doInBackground(Params…) 和onPostExecute(Result)
  • doInBackground(Params…) 后台执行,用来写耗时操作,但这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以 调用publicProgress(Progress…)来更新任务的进度。
  • onPostExecute(Result)  相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回
    ParserTask类用于将服务器中获取的数据解析为Adapter可以解析的ListEntity<T>格式,并把数据添加到adapter中。
    下面代码在BaseListFragment中:

    class ParserTask extends AsyncTask<Void, Void, String> {        private final byte[] reponseData;        private boolean parserError;        private List<T> list;//从服务器获取的数据保存在形参中,传进来赋值给responseData        public ParserTask(byte[] data) {            this.reponseData = data;        }        @Override        protected String doInBackground(Void... params) {            try {                //解析数据为ListEntity格式                ListEntity<T> data = parseList(new ByteArrayInputStream(                        reponseData));                list = data.getList();            } catch (Exception e) {                e.printStackTrace();                parserError = true;            }            return null;        }        @Override        protected void onPostExecute(String result) {            super.onPostExecute(result);            //将数据赋值到mAdapter,在ListView中展示                mAdapter.addData(data);        }    }

四、新闻获取展示界面-NewsFragment

1、概述

    根据类的不同,这里发出向服务器获取数据的请求,赋值不同的adapter(这里为NewsAdapter)。因为BlogFragment(从服务器获取博客数据)和NewsFragment同继承于BaseListFragment<T>,所以该类要反映出它们的差异。

/** * @function 综合-资讯/热点界面 */public class NewsFragment extends BaseListFragment<News> {    protected static final String TAG = NewsFragment.class.getSimpleName();    //之前使用的是 在外部定义adapter作为参数传进来    @Override    protected ListBaseAdapter<News> getListAdapter() {        return new NewsAdapter();    }      //解析List    @Override    protected NewsList parseList(InputStream is) throws Exception {        NewsList list = null;        try {            list = XmlUtils.toBean(NewsList.class, is);        } catch (NullPointerException e) {            list = new NewsList();        }        return list;    }    @Override    protected void sendRequestData() {        //mHandler在BaseListFragment中定义,mHandler监测从服务器中获取的数据        OSChinaApi.getNewsList(mCatalog, mCurrentPage, mHandler);    }}

2、定义用于传递参数获取数据的接口

    为获取新闻制定接口。

 

/**     * 获取新闻列表     * @param catalog     *            类别 (1,2,3)     * @param page     *            第几页     * @param handler     */    public static void getNewsList(int catalog, int page,            AsyncHttpResponseHandler handler) {        RequestParams params = new RequestParams();        params.put("catalog", catalog);        params.put("pageIndex", page);        params.put("pageSize", 20);//默认分页         if (catalog == NewsList.CATALOG_WEEK) {            params.put("show", "week");        } else if (catalog == NewsList.CATALOG_MONTH) {            params.put("show", "month");        }        //第一个参数为相对地址        ApiHttpClient.get("action/api/news_list", params, handler);    }

3、Android-Async-Http架构的使用 

    Android- Async-Http的使用非常简单,通过AsyncHttpClient发起请求就可以了,如果需要添加参数,直接传一个RequestParams过 去,而且参数可以是String、File和InputStream,可以很方便地上传文件。在上面的接口,就是用于为AsyncHttpClient准备的。

    每个请求都需要传一个ResponseHandlerInterface的实例用以接收请求结果或请求失败,请求结束等通知,一般是AsyncHttpResponseHandler的子类。

    基本用法:

AsyncHttpClient client = new AsyncHttpClient();client.get("http://www.google.com", new AsyncHttpResponseHandler() {    @Override    public void onSuccess(String response) {        System.out.println(response);    }});
      开源中国源码中,将AsyncHttpResponseHandler的就收请求结果放到了BaseListFragment中,前面介绍过。
public class ApiHttpClient {    public static AsyncHttpClient client;    private static String API_URL = "http://www.oschina.net/%s";    public final static String HOST = "www.oschina.net";    public static void get(String partUrl, AsyncHttpResponseHandler handler) {        //一般的方法中handler为 new AsyncHttpResponseHandler()         client.get(getAbsoluteApiUrl(partUrl), handler);         log(new StringBuilder("GET ").append(partUrl).toString());     }    /*     * 到时候注意handler的触发和来源     */    public static void get(String partUrl, RequestParams params,            AsyncHttpResponseHandler handler) {        client.get(getAbsoluteApiUrl(partUrl), params, handler);        log(new StringBuilder("GET ").append(partUrl).append("&")                .append(params).toString());    }    public static String getAbsoluteApiUrl(String partUrl) {        String url = String.format(API_URL, partUrl);        Log.d("BASE_CLIENT", "request:" + url);        return url;    }//配置网络信息    public static void setHttpClient(AsyncHttpClient c) {        client = c;        client.addHeader("Accept-Language", Locale.getDefault().toString());        client.addHeader("Host", HOST);        client.addHeader("Connection", "Keep-Alive");        client.getHttpClient().getParams()                .setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);        setUserAgent(ApiClientHelper.getUserAgent(AppContext.getInstance()));    }}

4、存储系统信息的全局类-AppContext

   AppContext类继承于Application,Application是android框架的一个系统组件,当android程序启动时系统会创建一个 application对象,用来存储系统的一些信息。android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例 (singleton)模式的一个类.且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。
   在这里初始化网络请求。
public class AppContext extends BaseApplication{//BaseApplication继承于Application    private static AppContext instance;    @Override    public void onCreate() {        super.onCreate();        instance = this;        init();    }    private void init() {        // 初始化网络请求        AsyncHttpClient client = new AsyncHttpClient();        ApiHttpClient.setHttpClient(client);    }}
     demo图片展示,就这一个界面。demo地址 开源中国源码学习数据篇(一)之android-async-http框架和AsyncTask。  
       






0 0
原创粉丝点击