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

    今天来进行数据(从开源中国服务器上面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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值