Android开源项目LifeUtil 之网络请求

在LifeUtil项目中,我们的“阅读”模块和“图片”模块都需要请求网络数据。
效果如下图:
这里写图片描述

无论是图片展示还是右边的文字项,都得获取网络数据。所以,有必要单独拿出来讲讲。这里先声明一下,阅读和图片模块中除美女专题外数据均是用Jsoup去网上爬取,(仅做学习交流,如有侵权,立即删除)。
这里的数据获取有两种方式:

  • “图片”模块中的美女专题,我在项目中使用了RxJava+Retofit +Gson解析。然后使用Glide加载展示图片。

  • “其他的”,使用Jsoup爬取。

一、Gson解析Json
下面是RxJava+Retrofit+Gson解析网络数据的代码模板:

  • Retofit管理类

封装了Retrofit,并以Gson来解析Json格式的数据。


public class RetrofitManager {

    private static RetrofitManager instance;
    private static Retrofit retrofit;
    private static Gson gson;
    private static String cookie = "";
    private static final String BASE_URL ="";

    public RetrofitManager() {

        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(httpClient())
                .addConverterFactory(GsonConverterFactory.create(gson()))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
    }

    public static void reset() {
        instance = null;
    }

    public <T> T create(Class<T> service) {
        return retrofit.create(service);
    }

    public static RetrofitManager getInstance() {

        if (instance == null) {
            synchronized (RetrofitManager.class) {
                instance = new RetrofitManager();
            }
        }
        return instance;
    }

    private static OkHttpClient httpClient() {
        return new OkHttpClient.Builder()
                .connectTimeout(15, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true)
                .build();
    }

    private  Gson gson() {
        if (gson == null) {
            synchronized (RetrofitManager.class) {
                gson = new GsonBuilder().setLenient().create();
            }
        }
        return gson;
    }
}
  • API工厂类
    封装所有的API,并以单例模式返回。
public class ApiFactory {

    //用于同步处理
    protected static final Object monitor = new Object();

    private static GirlsController girlsController;

    public static GirlsController getGirlsController(){

        if(girlsController==null){
            synchronized (monitor){
                girlsController =RetrofitManager.getInstance().create(GirlsController.class);
            }
        }

        return girlsController;
    }
}
  • 具体Retrofit数据接口实现(这里是美女专题的接口)
public interface GirlsController {

    @GET ("http://gank.io/api/data/%E7%A6%8F%E5%88%A9/6/{page}")
    Observable<BaseGankResponse<List<Girl>>> getGank(@Path("page") String page);

    @GET ("http://gank.io/api/data/%E7%A6%8F%E5%88%A9/10/{page}")
    Observable<ResponseBody> getGankBody(@Path("page") String page);

}

上面三个步骤创建好了之后,就可以在MainActivity中使用RxJava调用,实现网络数据的请求了。
代码如下:

 public void getGank(int curPage) {

        ApiFactory.getGirlsController().getGank(curPage + "").subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<BaseGankResponse<List<Girl>>>() {
                    @Override
                    public void onCompleted() {
                        ((MainActivity) getActivity()).showSnack("加载完成");
                        binding.swipRefreshLayout.setRefreshing(false);
                    }

                    @Override
                    public void onError(Throwable e) {
                        ((MainActivity) getActivity()).showSnack("加载失败");
                        binding.swipRefreshLayout.setRefreshing(false);
                    }

                    @Override
                    public void onNext(BaseGankResponse<List<Girl>> response) {
                        for (Girl girl : response.datas) {
                            if (girl.getHeight() == 0) {
                                girl.setHeight((new Random().nextInt(100)) + 500);
                            }
                        }
                        //Adapter更新数据
                        if (isRefresh) {
                            adapter.setNewData(response.datas);
                        } else {
                            adapter.addDatas(response.datas);
                        }
                    }

                });
    }

当然,我们不能把Girl类忘掉的,否则Gson是解析不出来数据的。

GirlBean类


public class Girl implements Serializable {

    private String url;

    @SerializedName("who")
    String name ;
    @SerializedName("desc")
    String date;

     public Girl(String url) {
        this.url = url;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

这样,数据请求就完成了。然后在Adapter中使用Glide加载显示图片就ok了。可以看到使用RxJava很方便的帮我们解决了异步的问题,而不用在数据加载完成后使用Handler机制切换回到主线程进行UI操作。

二、Jsoup爬取网页

 /**
     * 从服务器上获取数据
     */
    public void getDataFromServer() {

        final String url =  getArguments().getString("url");

        subscription = Observable.just(url).subscribeOn(Schedulers.io()).map(new Func1<String, List<PhotoItem>>() {
            @Override
            public List<PhotoItem> call(String s) {
                List<PhotoItem> photoList = new ArrayList<>();
                try {
                    Document doc = Jsoup.connect(url).timeout(5000).get();
                    Element element = doc.select("div.wrap").last();
                    Elements items = element.select("div.kboxgrid");
                    for (Element ele : items) {
                        PhotoItem item = new PhotoItem();
                        Element content = ele.select("div.boxgrid").first();
                        Element info = ele.select("div.citemqt").first();
                        String name = info.select("a").first().text();
                        String imgUrl = content.select("img").first().attr("src");
                        String from =content.select("a").first().attr("href");
                        String date =info.select("a").last().text();
                        item.setName(name);
                        item.setImg(imgUrl);
                        item.setFrom(from);
                        item.setDate(date);
                        photoList.add(item);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return photoList;
            }
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<List<PhotoItem>>() {
            @Override
            public void onCompleted() {
                binding.swipeRefreshLayout.setRefreshing(false);
                ((MainActivity) getActivity()).showSnack("加载完成");
            }

            @Override
            public void onError(Throwable e) {
                ((MainActivity) getActivity()).showSnack("加载失败");
                binding.swipeRefreshLayout.setRefreshing(false);
            }

            @Override
            public void onNext(List<PhotoItem> list) {
                adapter.setNewData(list);
            }
        });
    }

这里主要是在map方法中将url使用Jsoup解析html,然后获取到我们所需的类,设置到Adpater中就搞定了。

上一篇:Android开源项目LifeUtil 之Base类
下一篇:Android开源项目LifeUtil 之数据展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值