WanAndroid实战——首页文章

前情回顾:
1.WanAndroid实战——首页Banner

前面完成了首页Banner的实现,本次继续来完成首页文章的获取和显示。

按照惯例,先上实现过的效果图。

首页文章效果

1.相关布局文件

首页文章的展示使用的是recycleView,每一项使用的是cardview来进行,因此,先在gradle中引入需要的依赖。


    //cardview
    implementation 'com.android.support:cardview-v7:28.0.0'

    //recycleview
    implementation 'com.android.support:recyclerview-v7:28.0.0'

activity_main.xml文件中添加recycleView的相关内容,修改后的文件如下:





    


    


article_item.xml文件作为每一项的布局,这里使用cardView作为跟布局,文件内容和布局效果如下:

布局效果



    

        

        


        

        


        


        


    



  1. 使用tools命名空间,用来展示布局效果,并且编译的时候不会编译进去,包括去掉一些警告,如ImageView的contentDescription属性。
  2. 使用Guideline,用来保证textView不会因为内容过长而遮挡其它控件的显示。

2.准备adapter

根据玩Android的开放API接口,我们知道首页数据的格式

https://www.wanandroid.com/article/list/0/json

方法:GET
参数:页码,拼接在连接中,从0开始。
点击查看示例:https://www.wanandroid.com/article/list/1/json。

可以直接复制示例内容后通过GsonFormat自动生成,具体的可以查看我的上一篇文章。生成的类名为MainArticleBean.java,记得加上toString方法,方便自己调试。

ArticleAdapter.java

package com.tom.wanandroid.adapter;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.tom.wanandroid.R;
import com.tom.wanandroid.bean.MainArticleBean;

import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * 

Title: ArticleAdapter

*

Description: 文章适配器

* * @author tom * @date 2019/3/9 10:15 **/ public class ArticleAdapter extends RecyclerView.Adapter { private Context mContext; private List mBeans; public void setBeans(MainArticleBean beans) { mBeans = beans.getData().getDatas(); } public ArticleAdapter(RecyclerView recyclerView) { mContext = recyclerView.getContext(); } @NonNull @Override public ArticleHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.article_item, parent, false); return new ArticleHolder(view); } @Override public void onBindViewHolder(@NonNull ArticleHolder articleHolder, int i) { if (mBeans != null) { MainArticleBean.DataBean.DatasBean bean = mBeans.get(i); articleHolder.mArticleTitle.setText(Html.fromHtml(bean.getTitle(), Html.FROM_HTML_MODE_COMPACT)); articleHolder.mArticleAuthor.setText(String.format(mContext.getResources().getString(R.string.article_author),bean.getAuthor())); articleHolder.mArticleTime.setText(bean.getNiceDate()); String category = String.format(mContext.getResources().getString(R.string.article_category), bean.getSuperChapterName(), bean.getChapterName()); articleHolder.mArticleClassify.setText(Html.fromHtml(category, Html.FROM_HTML_MODE_COMPACT)); } } @Override public int getItemCount() { return mBeans != null ? mBeans.size() : 0; } class ArticleHolder extends RecyclerView.ViewHolder { @BindView(R.id.article_title) TextView mArticleTitle; @BindView(R.id.article_author) TextView mArticleAuthor; @BindView(R.id.article_classify) TextView mArticleClassify; @BindView(R.id.article_collection) ImageView mArticleCollection; @BindView(R.id.article_time) TextView mArticleTime; ArticleHolder(@NonNull View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } }

这里有一点需要说明,因为获取的数据为网络数据,且部分数据会带有html中的标签并且使用unicode编码,如果不处理的话会直接显示出unicode码,不好看。这里使用的是Html.fromHtml方法,里面的参数官网上面有说明。

3.在接口中增加相关的内容

分别增加MVP层的接口,比较简单,直接给出代码Contract.java

package com.tom.wanandroid.contract;

import com.tom.wanandroid.bean.BannerBean;
import com.tom.wanandroid.bean.MainArticleBean;

import io.reactivex.Observable;

/**
 * 

Title: Contract

*

Description:

* * @author tom * @date 2019/3/7 10:13 **/ public class Contract { public interface IMainModel { /** *

获取banner数据

* @return banner数据 */ Observable loadBanner(); /** *

获取首页文章

* @param number 页码 * @return 首页文章 */ Observable loadArticle(int number); } public interface IMainView { /** *

View 获取到数据后进行显示

* @param bean banner的数据 */ void loadBanner(BannerBean bean); /** *

展示首页文章信息

* @param bean 首页文章数据 */ void loadArticle(MainArticleBean bean); } public interface IMainPresenter{ /** *

首页banner

*/ void loadBanner(); /** *

加载首页文章

*/ void loadArticle(); } }

因为使用retorfit来获取网络数据,首先还是要增加接口。

IRetrofitData.java这里需要传入页码作为参数。

    /**
     * 

获取首页文章数据

* @param number 页码 * @return 返回首页文章 */ @GET("article/list/{number}/json") Observable loadMainArticle(@Path("number") int number);

4.实现接口

接口加完以后,就来处理报错吧,哪里报错改哪里,so easy!

MainModel.java和之前获取首页数据一样的套路。

    @Override
    public Observable loadArticle(int number) {
        Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        IRetrofitData retrofitData = retrofit.create(IRetrofitData.class);


        return retrofitData.loadMainArticle(number);
    }

MainPresenter.java增加首页文章的相关内容,这里固定获取第一页的数据(传入参数为0)。

    @Override
    public void loadArticle() {

        mModel.loadArticle(0)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        mCompositeDisposable.add(d);
                    }

                    @Override
                    public void onNext(MainArticleBean bean) {
                        if (isViewAttached()) {
                            getView().loadArticle(bean);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                    }

                    @Override
                    public void onComplete() {

                    }
                });

    }

MainActivity.java,这里有一点小修改,将之前初始化数据的方法由init中放到了onresume中。

    @Override
    protected void onResume() {
        super.onResume();
        mPresenter.loadBanner();
        mPresenter.loadArticle();
    }

    @Override
    public void loadArticle(MainArticleBean bean) {
        mArticleContent.setLayoutManager(new LinearLayoutManager(this));
        if (bean.getErrorCode() == 0) {

            ArticleAdapter adapter = new ArticleAdapter(mArticleContent);
            adapter.setBeans(bean);
            mArticleContent.setAdapter(adapter);

        }

    }

到这里为止,关键内容基本都OK了,程序跑起来就可以看到前面的效果图了。

这里给出用到的资源文件

colors.xml



    #008577
    #00574B
    #D81B60
    #F0F0F0


dimens.xml



    200dp
    12dp
    15dp
    10dp
    10dp
    15dp
    30dp

strings.xml中文和英文是两个夹子的,这里写在一起了。



    WanAndroid

    author:%1$s
    category:%1$s/%2$s






    玩Android
    作者:%1$s
    分类:%1$s/%2$s


用到的图标:

collect_disable.png
collect_enable.png

后续更新:

3.WanAndroid实战——内容显示
4.WanAndroid实战——刷新加载
5.WanAndroid实战——网络判断

你可能感兴趣的:(WanAndroid实战——首页文章)