OkHttp实战——实现《即时新闻》App

先来段引言:okhttp真的好用,java基础真的要学好。哈哈哈~

看看效果吧:



进入正题,整体思路是:用TabLayout和ViewPager划分出四个新闻类型的区域,这四个区域分别用四个fragment来装,fragment里面就是一个RecyclerView,用okhttp获取数据并放到RecyclerView中。

java和xml文件概览:                                    

首先建立主布局:NewsListActivity

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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"
    android:orientation="vertical"
    tools:context=".view.activity.NewsListActivity">

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="#FF6666"
        app:tabTextColor="#FFC0C0"
        app:tabSelectedTextColor="#fff"
        app:tabMode="fixed"
        app:tabIndicatorColor="#fff"/>
    <!--app:tabIndicatorColor="#CC33FF"
        app:tabIndicatorHeight="8dp"
        表示提示条高度及颜色-->

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_weight="1">

    </android.support.v4.view.ViewPager>

</LinearLayout>

很简单,就是LinearLayout里面放一个TabLayout和一个ViewPager。

然后通过fragmentPagerAdapter来加载四个fragment:



此处不再赘述,用法详见:Android 导航条效果实现(六) TabLayout+ViewPager+Fragment

我这里没有用到动态加载,后续会更新。

下一步就是每个fragment里面都放一个RecyclerView,这里放出社会类新闻的fragment,以此类推...


然后就是往RecyclerView里面填数据,新建一个子项布局news_item.xml,里面用LinearLayout装ImageView+textView存放新闻的图片和标题时间等,也是比较简单的,代码就不放了:


怎么放数据进去,首先要获取数据,那么就要用到好用的okhttp了。

下面这段代码就是okhttp的异步加载:

public void asyncHttpRequest(String type){
    Log.i(TAG, "加载到asyncHttpRequest()");
    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
            .url("http://v.juhe.cn/toutiao/index?type="+type+"&key=65d4c89f2460e131bd8b288f3f70bff6")
            .build();
    okhttp3.Call call = client.newCall(request);
    call.enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            ToastUtil.showToast(context,"新闻加载失败");
        }

        @Override
        public void onResponse(Call call, final Response response) throws IOException {
            Log.d(TAG, "请求成功");
            Log.d(">>>onResponse>>>当前线程", Thread.currentThread().getName());
            final String responseData = response.body().string();
            Log.d(TAG, responseData);
            parseData(responseData);
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ToastUtil.showToast(activity,"成功获取数据");
                }
            });
        }
    });
}

OkHttp用法详见:OKHttp使用详解(菜鸟一枚,暂不懂原理,只能当搬运工啦,嘿嘿~)

这里通过传入申请到的Api来获取数据,返回的response就是我获取到的数据啦,这里要注意,要打印出来要用到response.body().string(),而这个方法只能调用一次,所以声明一个变量responseData来存放。这是json格式的字符串,我们要把它解析出来为我们所用。首先我们要了解其结构,直接把这个带AppKey和参数的网址打开是这样的字符串:

那么我们就要建立一个对应的实体类,这里有两个方法:一个是通过在线Json解析工具来生成实体类然后复制到我们新建的实体类中,还有一种是在Android studio中安装GsonFormat插件,自动生成。都挺好用,看个人习惯。Gsonformat就像下面这样,Alt+S打开插件,把json数据粘贴上去,如果格式正确,点击ok就自动生成代码啦。


现在我们就有能装我们解析出来的数据的实体类啦,然后就开始解析:


通过谷歌官方的解析库Gson来解析成我们要的格式,这里解析成了一个List,随手打印一下,可以拿到标题啦,再写几句代码测试下放到界面上(注意这里要在主线程即UI线程进行),发现可以啦,于是可以愉快地进行展示操作了。

现在我们已经获取到我们想要的全部数据了,接下来就是放进界面的过程,即放入RecyclerView。这里我们需要一个自定义NewsAdapter来将RecyclerView和数据关联起来:

public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {

    private List<NewsBean.Result.Data> mNewsList;

    public NewsAdapter(List<NewsBean.Result.Data> mNewsList) {
        this.mNewsList = mNewsList;
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        private LinearLayout linearLayout;
        private ImageView newsImage;
        private TextView newsTitle;
        private TextView newsSrc;
        private TextView newsTime;
        public ViewHolder(View view) {
            super(view);
            linearLayout = view.findViewById(R.id.linear_layout);
            newsImage = view.findViewById(R.id.iv_news_list_image);
            newsTitle = view.findViewById(R.id.tv_news_list_title);
            newsSrc = view.findViewById(R.id.tv_news_list_real_type);
            newsTime = view.findViewById(R.id.tv_news_list_time);
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
        final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        final NewsBean.Result.Data news = mNewsList.get(position);
        String image = news.getThumbnail_pic_s().toString();
//        Log.i(">>>adapter>>>>>image", mNewsList.get(0).getThumbnail_pic_s());
        Glide.with(holder.itemView.getContext()).load(image).into(holder.newsImage);
        holder.newsTitle.setText(news.getTitle());
        holder.newsSrc.setText(news.getAuthor_name());
        holder.newsTime.setText(news.getDate());
        holder.linearLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(v.getContext(),NewsInfoActivity.class);
                intent.putExtra("url",news.getUrl());
                v.getContext().startActivity(intent);
            }
        });
    }

    @Override
    public int getItemCount() {
        return mNewsList.size();
    }


}

关于这个RecyclerView的用法我前面的文章有demo,也不详细讲了。这样子我们的数据展示工作就完成啦。最后想点击新闻列表中的每个单项查看新闻的详细信息,就新建了一个NewsInfoActivity,里面就一个控件WebView,用来加载网页。在NewsAdapter里面将我们数据中的网页url取出来,传到WebView进行加载就行了。

在Adapter中传值:


在NewsInfoActivity中接收并加载:


大功告成!

.

.

.

.

.

.

最后是总结:

1.关于okhttp的同步和异步加载,对于同步请求在请求时需要开启子线程,请求成功后需要跳转到UI线程修改UI。异步加载不用再次开启子线程,但回调方法是执行在子线程中,所以在更新UI时还要跳转到UI线程中。

2.response.body().string这个方法只能调用一次,超过一次会报错,想重复使用就要放到一个变量中。

3.本来只想把网络请求这部分内容封装,结果发现返回的值在try里面怎么都取不出来,困扰了一个星期,java基础不过关。。。无奈,解析和UI操作都一起封装了,不过这样倒是让主界面代码看起来简洁了许多。

4.试着用retrofit写了个demo,以为代码量会比okhttp少很多,想进行替换,结果发现差不多,应该是我还没理解到其精髓,后续应该会将此程序改为retrofit。

5.过程中遇到好多异常,忘了记录下来解决方法,以后注意。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值