TouTiao开源项目 分析笔记10 实现通用普通文章片段页面
1.RxJava的Observable数据操作符总结
1.1.Map操作符
Map操作符对原始Observable发射的没一项数据应用一个你选择的函数,
然后返回一个发射这些结果的Observable。
简单例子:
private void testMap() { String[]items = {"just1","just2","just3","just4","just5","just6"}; Observable<String> myObservable = Observable.from(items) .map(new Func1<String, String>() { @Override public String call(String s) { return mapInfo(s); } }); Subscriber<String> mySubscriber = new Subscriber<String>() { @Override public void onNext(String s) { System.out.println("onNext................."+s); } @Override public void onCompleted() { System.out.println("onCompleted................."); } @Override public void onError(Throwable e) { System.out.println("onError...................."); } }; myObservable.subscribe(mySubscriber); }
里面定义的函数为:
private String mapInfo(String s){ return s+" had mapped;"; }
运行结果:
1.2.cast操作符
cast操作符将原始Observable发射的每一项数据都强制转换为一个指定的类型,然后再发射数据,它是map的
一个特殊版本。
注意:所相互转换的类之间需要存在某种关系,如继承、实现。
简单例子:
List<Machine> items = new ArrayList<>();
for (int i=0;i<3;i++){ items.add(new Computer("computer"+i,"material"+i)); } Observable<Computer> myObservable = Observable.from(items) .cast(Computer.class); .cast(TestCastEntity.class); Subscriber<Computer> mySubscriber = new Subscriber<Computer>() { @Override public void onNext(Computer s) { System.out.println("onNext................."+s.name+".........."+s.material); } @Override public void onCompleted() { System.out.println("onCompleted................."); } @Override public void onError(Throwable e) { System.out.println("onError...................."); } }; myObservable.subscribe(mySubscriber); } public class Machine { public String name; public Machine(String name){ this.name = name; } } public class Computer extends Machine{ public String material; public Computer(String name,String material){ super(name); this.material = material; } }
运行结果:
1.3.encode操作符
encode将一个发射字符串的Observable变换为一个发射字节数组(这个字节数组按照原始字符串中的多字节字符边界划分)
的Observable。
1.4.byLine操作符
byLine将一个发射字符串的Observable变换为一个按行发射来自原始Observable的字符串的Observable。
1.5.flatmap操作符
FlatMap操作符使用一个指定的函数对原始Observable发射的每一项数据执行变换操作。
这个函数返回一个本身也发射数据的Observable,然后FlatMap合并这些Observable发射的数据。
最后将合并后的结果当做它自己的数据序列发射。
FlatMap通过一个函数将原来的数据的每一项进行转换,并将返回的数据进行Observable包装。
然后将所有这些Observable转换成一个Observable发射。
所执行的结果可能和原数据items中数据的顺序不一致。
简单例子:
private void testFlatMap() { Integer[]items = {1,2,3,4,5,6}; Observable<String> myObservable = Observable.from(items) .flatMap(new Func1<Integer, Observable<String>>() { @Override public Observable<String> call(Integer i) { return Observable.just(flatMapInfo(i)); } }); Subscriber<String> mySubscriber = new Subscriber<String>() { @Override public void onNext(String s) { System.out.println("onNext................."+s); } @Override public void onCompleted() { System.out.println("onCompleted................."); } @Override public void onError(Throwable e) { System.out.println("onError...................."); } }; myObservable.subscribe(mySubscriber); } private String flatMapInfo(Integer i){ return "flatmap" + i; }
运行结果:
1.6.flatMapIterable操作符
使用iterable作为源数据,再将其转换成多个observable
简单案例:
Integer[]items = {1,2,3,4,5,6}; Observable<String> myObservable = Observable.from(items) .flatMapIterable(new Func1<Integer, Iterable<? extends String>>() { @Override public Iterable<String> call(Integer integer) { ArrayList<String> strings = new ArrayList<String>(); strings.add("iterable"+integer); return strings; } }); Subscriber<String> mySubscriber = new Subscriber<String>() { @Override public void onNext(String s) { System.out.println("onNext................."+s); } @Override public void onCompleted() { System.out.println("onCompleted................."); } @Override public void onError(Throwable e) { System.out.println("onError...................."); } }; myObservable.subscribe(mySubscriber);
运行结果:
1.7.concatMap操作符
concatMap操作符,它类似于最简单版本的flatMap,但是它按次序连接而不是合并那些生成的Observables,
然后产生自己的数据序列。
1.8.switchMap操作符
switchMap操作符,它和flatMap很像,除了一点:当原始Observable发射一个新的数据(Observable)时,
它将取消订阅并停止监视产生执行之前那个数据的Observable,只监视当前这一个。
简单例子:
Integer[]items = {1,2,3,4,5,6}; Observable<String> myObservable = Observable.from(items) .switchMap(new Func1<Integer, Observable<String>>() { @Override public Observable<String> call(Integer integer) { return Observable.just(integer+"").subscribeOn(Schedulers.newThread()); } }); Subscriber<String> mySubscriber = new Subscriber<String>() { @Override public void onNext(String s) { System.out.println("onNext................."+s); } @Override public void onCompleted() { System.out.println("onCompleted................."); } @Override public void onError(Throwable e) { System.out.println("onError...................."); } }; myObservable.subscribe(mySubscriber);
运行结果:
1.9.split操作符
split操作符将一个发射字符串的Observable转换为另一个发射字符串的Observable,
只不过,后者将原始的数据序列当做一个数据流,使用一个正则表达式边界分割它们,然后合并发射分割的结果。
1.10.filter过滤操作符
作用:过滤,筛选,添加对事件是否需要发送的判断。
示例用法:
Observable.just(1, 2, 3, 4, 5, 6)//创建了一个有6个数字的被观察者 .filter(new Predicate<Integer>() {//添加筛选器 @Override public boolean test(Integer integer) throws Exception {
//对每个事件进行筛选,返回true的保留 return integer % 2 == 0; } }) .subscribe(getObserver());//这里的观察者依然不重要
返回结果==>2,4,6
1.11.toList()函数
把循环请求下来的内容生成一个List。
1.11.参考文献
2.基础Bean类
2.1.实现Parcelable接口的方法
参考文章:博客-Android中Parcelable接口的用法。
实现Parcelable就是为了进行序列化,那么,为什么要序列化?
1)永久性保存对象,保存对象的字节序列到本地文件中; 2)通过序列化对象在网络中传递对象; 3)通过序列化在进程间传递对象。
Parcelable接口的定义。
public interface Parcelable { //内容描述接口,基本不用管 public int describeContents(); //写入接口函数,打包 public void writeToParcel(Parcel dest, int flags); //读取接口,目的是要从Parcel中构造一个实现了Parcelable的类的实例处理。因为实现类在这里还是不可知的,所以需要用到模板的方式,继承类名通过模板参数传入 //为了能够实现模板参数的传入,这里定义Creator嵌入接口,内含两个接口函数分别返回单个和多个继承类实例 public interface Creator<T> { public T createFromParcel(Parcel source); public T[] newArray(int size); } }
实现Parcelable步骤。
1)implements Parcelable 2)重写writeToParcel方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从 Parcel容器获取数据 3)重写describeContents方法,内容接口描述,默认返回0就可以 4)实例化静态内部对象CREATOR实现接口Parcelable.Creator
注意点:
其中public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写。
需重写本接口中的两个方法:createFromParcel(Parcel in)
实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层,
newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话即可(return new T[size])
,供外部类反序列化本类数组使用。
简而言之:通过writeToParcel将你的对象映射成Parcel对象,
再通过createFromParcel将Parcel对象映射成你的对象。
也可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,
在通过createFromParcel从流里读取对象,只不过这个过程需要你来实现,
因此写的顺序和读的顺序必须一致。
简单案例:
public class MyParcelable implements Parcelable { private int mData; public int describeContents() { return 0; } public void writeToParcel(Parcel out, int flags) { out.writeInt(mData); } public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() { public MyParcelable createFromParcel(Parcel in) { return new MyParcelable(in); } public MyParcelable[] newArray(int size) { return new MyParcelable[size]; } }; private MyParcelable(Parcel in) { mData = in.readInt(); } }
2.2.MultiNewsArticleBean通用的新闻文章Bean类,将数据封装到里面的content中了。
public class MultiNewsArticleBean { /** * login_status : 0 * total_number : 15 * has_more : true * post_content_hint : 分享今日新鲜事 * show_et_status : 0 * feed_flag : 0 * action_to_last_stick : 1 * message : success * has_more_to_refresh : true * tips : {"display_info":"今日头条推荐引擎有15条更新","open_url":"","web_url":"","app_name":"今日头条","package_name":"","display_template":"今日头条推荐引擎有%s条更新","type":"app","display_duration":2,"download_url":""} */ private int login_status; private int total_number; private boolean has_more; private String post_content_hint; private int show_et_status; private int feed_flag; private int action_to_last_stick; private String message; private boolean has_more_to_refresh; private TipsBean tips; private List<DataBean> data; public int getLogin_status() { return login_status; } public void setLogin_status(int login_status) { this.login_status = login_status; } public int getTotal_number() { return total_number; } public void setTotal_number(int total_number) { this.total_number = total_number; } public boolean isHas_more() { return has_more; } public void setHas_more(boolean has_more) { this.has_more = has_more; } public String getPost_content_hint() { return post_content_hint; } public void setPost_content_hint(String post_content_hint) { this.post_content_hint = post_content_hint; } public int getShow_et_status() { return show_et_status; } public void setShow_et_status(int show_et_status) { this.show_et_status = show_et_status; } public int getFeed_flag() { return feed_flag; } public void setFeed_flag(int feed_flag) { this.feed_flag = feed_flag; } public int getAction_to_last_stick() { return action_to_last_stick; } public void setAction_to_last_stick(int action_to_last_stick) { this.action_to_last_stick = action_to_last_stick; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public boolean isHas_more_to_refresh() { return has_more_to_refresh; } public void setHas_more_to_refresh(boolean has_more_to_refresh) { this.has_more_to_refresh = has_more_to_refresh; } public TipsBean getTips() { return tips; } public void setTips(TipsBean tips) { this.tips = tips; } public List<DataBean> getData() { return data; } public void setData(List<DataBean> data) { this.data = data; } public static class TipsBean { /** * display_info : 今日头条推荐引擎有15条更新 * open_url : * web_url : * app_name : 今日头条 * package_name : * display_template : 今日头条推荐引擎有%s条更新 * type : app * display_duration : 2 * download_url : */ private String display_info; private String open_url; private String web_url; private String app_name; private String package_name; private String display_template; private String type; private int display_duration; private String download_url; public String getDisplay_info() { return display_info; } public void setDisplay_info(String display_info) { this.display_info = display_info; } public String getOpen_url() { return open_url; } public void setOpen_url(String open_url) { this.open_url = open_url; } public String getWeb_url() { return web_url; } public void setWeb_url(String web_url) { this.web_url = web_url; } public String getApp_name() { return app_name; } public void setApp_name(String app_name) { this.app_name = app_name; } public String getPackage_name() { return package_name; } public void setPackage_name(String package_name) { this.package_name = package_name; } public String getDisplay_template() { return display_template; } public void setDisplay_template(String display_template) { this.display_template = display_template; } public String getType() { return type; } public void setType(String type) { this.type = type; } public int getDisplay_duration() { return display_duration; } public void setDisplay_duration(int display_duration) { this.display_duration = display_duration; } public String getDownload_url() { return download_url; } public void setDownload_url(String download_url) { this.download_url = download_url; } } public static class DataBean { /** * content : {"log_pb": {"impr_id": "201705182052000100040340182987C4"}, "read_count": 1068313, "media_name": "\u65b0\u534e\u7f51", "ban_comment": 0, "abstract": "\u65b0\u534e\u7f51\u8bb0\u8005 \u738b\u5b50\u6656\u3010\u5b66\u4e60\u8fdb\u884c\u65f6\u301115\u65e5\u95ed\u5e55\u7684\u201c\u4e00\u5e26\u4e00\u8def\u201d\u56fd\u9645\u5408\u4f5c\u9ad8\u5cf0\u8bba\u575b\u53d6\u5f97\u4e86\u4e3e\u4e16\u77a9\u76ee\u7684\u4e30\u7855\u6210\u679c\u3002\u65b0\u534e\u793e\u300a\u5b66\u4e60\u8fdb\u884c\u65f6\u300b\u539f\u521b\u54c1\u724c\u680f\u76ee\u201c\u8bb2\u4e60\u6240\u201d\u4eca\u5929\u63a8\u51fa\u6587\u7ae0\uff0c\u4ece\u201c\u627f\u8bfa\u201d\u548c\u201c\u8df5\u884c\u201d\u7684\u89d2\u5ea6\uff0c\u4e3a\u60a8\u89e3\u8bfb\u4e60\u8fd1\u5e73\u5728\u8fd9\u6b21\u8bba\u575b\u4e0a\u7684\u91cd\u8981\u6f14\u8bb2\u3002", "image_list": [], "ban_bury": 1, "has_video": false, "article_type": 0, "tag": "news_politics", "forward_info": {"forward_count": 34}, "has_m3u8_video": 0, "keywords": "\u591a\u8fb9\u4e3b\u4e49,\u4e1d\u7ef8\u4e4b\u8def,\u5171\u8d62,\u6784\u5efa\u4eba\u7c7b\u547d\u8fd0\u5171\u540c\u4f53,\u4e00\u5e26\u4e00\u8def", "rid": "201705182052000100040340182987C4", "label": "\u7f6e\u9876", "show_portrait_article": false, "user_verified": 0, "aggr_type": 1, "cell_type": 0, "article_sub_type": 0, "bury_count": 0, "title": "\u201c\u4e00\u5e26\u4e00\u8def\u201d\u2014\u2014\u4e60\u8fd1\u5e73\u4e4b\u8bfa", "ignore_web_transform": 1, "source_icon_style": 4, "tip": 0, "hot": 0, "share_url": "http://toutiao.com/group/6421262515992903938/?iid=0&app=news_article", "has_mp4_video": 0, "source": "\u65b0\u534e\u7f51", "comment_count": 14, "article_url": "http://news.xinhuanet.com/politics/2017-05/18/c_1120991501.htm", "filter_words": [], "share_count": 4806, "stick_label": "\u7f6e\u9876", "publish_time": 1495067173, "action_list": [{"action": 1, "extra": {}, "desc": ""}, {"action": 3, "extra": {}, "desc": ""}, {"action": 7, "extra": {}, "desc": ""}, {"action": 9, "extra": {}, "desc": ""}], "has_image": false, "cell_layout_style": 1, "tag_id": 6421262515992903938, "video_style": 0, "verified_content": "", "display_url": "http://toutiao.com/group/6421262515992903938/", "is_stick": true, "large_image_list": [], "item_id": 6421266422789308929, "is_subject": false, "stick_style": 1, "show_portrait": false, "repin_count": 11258, "cell_flag": 11, "user_info": {"verified_content": "", "avatar_url": "http://p3.pstatp.com/thumb/3658/7378365093", "user_id": 4377795668, "name": "\u65b0\u534e\u7f51", "follower_count": 0, "follow": false, "user_auth_info": "", "user_verified": false, "description": "\u4f20\u64ad\u4e2d\u56fd\uff0c\u62a5\u9053\u4e16\u754c\uff1b\u6743\u5a01\u58f0\u97f3\uff0c\u4eb2\u5207\u8868\u8fbe\u3002"}, "source_open_url": "sslocal://profile?uid=4377795668", "level": 0, "like_count": 3, "digg_count": 3, "behot_time": 1495111920, "cursor": 1495111920999, "url": "http://news.xinhuanet.com/politics/2017-05/18/c_1120991501.htm", "preload_web": 0, "user_repin": 0, "label_style": 1, "item_version": 0, "media_info": {"user_id": 4377795668, "verified_content": "", "avatar_url": "http://p2.pstatp.com/large/3658/7378365093", "media_id": 4377795668, "name": "\u65b0\u534e\u7f51", "recommend_type": 0, "follow": false, "recommend_reason": "", "is_star_user": false, "user_verified": false}, "group_id": 6421262515992903938, "middle_image": {}} * code : */ private String content; private String code; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } } }
这里用作API调用后返回的所有数据的一个大类,包括了很多杂项。
2.3.MultiNewsArticleDataBean通用的新闻文章数据Bean类。
这里将API调用后返回的所有数据中提取了重要的封装好的一个数据类型。
public class MultiNewsArticleDataBean implements Parcelable { public static final Creator<MultiNewsArticleDataBean> CREATOR = new Creator<MultiNewsArticleDataBean>() { @Override public MultiNewsArticleDataBean createFromParcel(Parcel in) { return new MultiNewsArticleDataBean(in); } @Override public MultiNewsArticleDataBean[] newArray(int size) { return new MultiNewsArticleDataBean[size]; } }; /** * log_pb : {"impr_id":"20170519112306010003048108480AA6"} * read_count : 156694 * media_name : 人民网 * ban_comment : 0 * abstract : 5月14日,国家主席***在北京人民大会堂举行宴会,欢迎出席“一带一路”国际合作高峰论坛的外方代表团团长及嘉宾。***发表致辞,代表中国政府和人民热烈欢迎各位贵宾的到来。新华社记者 刘卫兵摄孟夏之日,万物并秀。 * ban_bury : 1 * has_video : false * article_type : 1 * tag : news_politics * forward_info : {"forward_count":8} * has_m3u8_video : 0 * keywords : 自由贸易区,共同体,国际合作高峰论坛,自由化,祝酒辞 * rid : 20170519112306010003048108480AA6 * label : 置顶 * show_portrait_article : false * user_verified : 0 * aggr_type : 1 * cell_type : 0 * article_sub_type : 1 * bury_count : 0 * title : ***“一带一路”高峰论坛系列讲话十大高频词 * ignore_web_transform : 1 * source_icon_style : 5 * tip : 0 * hot : 0 * share_url : http://toutiao.com/group/6421272334078247169/?iid=0&app=news_article * has_mp4_video : 0 * source : 人民网 * comment_count : 2 * article_url : http://m2.people.cn/r/MV8xXzI5Mjg0OTA4XzQxMTgzN18xNDk1MDg3NTQx * filter_words : [] * share_count : 972 * stick_label : 置顶 * publish_time : 1495087541 * action_list : [{"action":1,"extra":{},"desc":""},{"action":3,"extra":{},"desc":""},{"action":7,"extra":{},"desc":""},{"action":9,"extra":{},"desc":""}] * has_image : true * cell_layout_style : 1 * tag_id : 6421272334078247000 * video_style : 0 * verified_content : * display_url : http://toutiao.com/group/6421272334078247169/ * is_stick : true * large_image_list : [] * item_id : 6421353649858938000 * is_subject : false * stick_style : 1 * show_portrait : false * repin_count : 2062 * cell_flag : 11 * user_info : {"verified_content":"","avatar_url":"http://p3.pstatp.com/thumb/ca400072481685ad43b","user_id":50502346173,"name":"人民网","follower_count":0,"follow":false,"user_auth_info":"","user_verified":false,"description":""} * source_open_url : sslocal://profile?uid=50502346173 * level : 0 * digg_count : 0 * behot_time : 1495164186 * article_alt_url : http://toutiao.com/group/article/6421272334078247169/ * cursor : 1495164186999 * url : http://m2.people.cn/r/MV8xXzI5Mjg0OTA4XzQxMTgzN18xNDk1MDg3NTQx * preload_web : 0 * user_repin : 0 * label_style : 1 * item_version : 0 * media_info : {"user_id":50502346173,"verified_content":"","avatar_url":"http://p3.pstatp.com/large/ca400072481685ad43b","media_id":50502346173,"name":"人民网","recommend_type":0,"follow":false,"recommend_reason":"","is_star_user":false,"user_verified":false} * group_id : 6421272334078247000 * middle_image : {"url":"http://p9.pstatp.com/list/300x196/207c000e549a17910c1c.webp","width":400,"url_list":[{"url":"http://p9.pstatp.com/list/300x196/207c000e549a17910c1c.webp"},{"url":"http://pb1.pstatp.com/list/300x196/207c000e549a17910c1c.webp"},{"url":"http://pb3.pstatp.com/list/300x196/207c000e549a17910c1c.webp"}],"uri":"list/207c000e549a17910c1c","height":225} * gallary_image_count : 1 * video_id : d4715d18819e4acc8b3012374dd4588f * video_detail_info : {"group_flags":32832,"video_type":0,"video_preloading_flag":1,"video_url":[],"direct_play":1,"detail_video_large_image":{"url":"http://p3.pstatp.com/video1609/17600009fb1bb36ce3ee","width":580,"url_list":[{"url":"http://p3.pstatp.com/video1609/17600009fb1bb36ce3ee"},{"url":"http://pb9.pstatp.com/video1609/17600009fb1bb36ce3ee"},{"url":"http://pb1.pstatp.com/video1609/17600009fb1bb36ce3ee"}],"uri":"video1609/17600009fb1bb36ce3ee","height":326},"show_pgc_subscribe":1,"video_third_monitor_url":"","video_id":"d4715d18819e4acc8b3012374dd4588f","video_watching_count":0,"video_watch_count":3502527} * image_list : [] * video_duration : 503 * group_flags : 32832 * filter_words : [{"id":"8:0","name":"重复、旧闻","is_selected":false},{"id":"9:1","name":"内容质量差","is_selected":false},{"id":"5:824751570","name":"来源:穹娱剪辑","is_selected":false},{"id":"1:548663395","name":"社会视频","is_selected":false},{"id":"6:15613","name":"银行","is_selected":false}] * action_list : [{"action":1,"extra":{},"desc":""},{"action":3,"extra":{},"desc":""},{"action":7,"extra":{},"desc":""},{"action":9,"extra":{},"desc":""}] * large_image_list : [{"url":"http://p3.pstatp.com/video1609/17600009fb1bb36ce3ee","width":580,"url_list":[{"url":"http://p3.pstatp.com/video1609/17600009fb1bb36ce3ee"},{"url":"http://pb9.pstatp.com/video1609/17600009fb1bb36ce3ee"},{"url":"http://pb1.pstatp.com/video1609/17600009fb1bb36ce3ee"}],"uri":"video1609/17600009fb1bb36ce3ee","height":326}] * like_count : 4787 */ private LogPbBean log_pb; private int read_count; private String media_name; private int ban_comment; @SerializedName("abstract") private String abstractX; private int ban_bury; private boolean has_video; private int article_type; private String tag; private ForwardInfoBean forward_info; // private boolean has_m3u8_video; private String keywords; private String rid; private String label; private boolean show_portrait_article; private int user_verified; private int aggr_type; private int cell_type; private int article_sub_type; private int bury_count; private String title; private int ignore_web_transform; private int source_icon_style; private int tip; private int hot; private String share_url; private int has_mp4_video; private String source; private int comment_count; private String article_url; private int share_count; private String stick_label; private int publish_time; private boolean has_image; private int cell_layout_style; private long tag_id; private int video_style; private String verified_content; private String display_url; // private boolean is_stick; private long item_id; private boolean is_subject; private int stick_style; private boolean show_portrait; private int repin_count; private int cell_flag; private UserInfoBean user_info; private String source_open_url; private int level; private int digg_count; private String behot_time; private String article_alt_url; private long cursor; private String url; private int preload_web; private int user_repin; private int label_style; private int item_version; private MediaInfoBean media_info; private long group_id; private MiddleImageBean middle_image; private int gallary_image_count; private String video_id; private VideoDetailInfoBean video_detail_info; private int video_duration; private int group_flags; private int like_count; private List<ImageListBean> image_list; public MultiNewsArticleDataBean() { } protected MultiNewsArticleDataBean(Parcel in) { read_count = in.readInt(); media_name = in.readString(); ban_comment = in.readInt(); abstractX = in.readString(); ban_bury = in.readInt(); has_video = in.readByte() != 0; article_type = in.readInt(); tag = in.readString(); // has_m3u8_video = in.readByte() != 0; keywords = in.readString(); rid = in.readString(); label = in.readString(); show_portrait_article = in.readByte() != 0; user_verified = in.readInt(); aggr_type = in.readInt(); cell_type = in.readInt(); article_sub_type = in.readInt(); bury_count = in.readInt(); title = in.readString(); ignore_web_transform = in.readInt(); source_icon_style = in.readInt(); tip = in.readInt(); hot = in.readInt(); share_url = in.readString(); has_mp4_video = in.readInt(); source = in.readString(); comment_count = in.readInt(); article_url = in.readString(); share_count = in.readInt(); stick_label = in.readString(); publish_time = in.readInt(); has_image = in.readByte() != 0; cell_layout_style = in.readInt(); tag_id = in.readLong(); video_style = in.readInt(); verified_content = in.readString(); display_url = in.readString(); item_id = in.readLong(); is_subject = in.readByte() != 0; stick_style = in.readInt(); show_portrait = in.readByte() != 0; repin_count = in.readInt(); cell_flag = in.readInt(); source_open_url = in.readString(); level = in.readInt(); digg_count = in.readInt(); behot_time = in.readString(); article_alt_url = in.readString(); cursor = in.readLong(); url = in.readString(); preload_web = in.readInt(); user_repin = in.readInt(); label_style = in.readInt(); item_version = in.readInt(); media_info = in.readParcelable(MediaInfoBean.class.getClassLoader()); group_id = in.readLong(); gallary_image_count = in.readInt(); video_id = in.readString(); video_detail_info = in.readParcelable(VideoDetailInfoBean.class.getClassLoader()); video_duration = in.readInt(); group_flags = in.readInt(); like_count = in.readInt(); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(read_count); dest.writeString(media_name); dest.writeInt(ban_comment); dest.writeString(abstractX); dest.writeInt(ban_bury); dest.writeByte((byte) (has_video ? 1 : 0)); dest.writeInt(article_type); dest.writeString(tag); // dest.writeByte((byte) (has_m3u8_video ? 1 : 0)); dest.writeString(keywords); dest.writeString(rid); dest.writeString(label); dest.writeByte((byte) (show_portrait_article ? 1 : 0)); dest.writeInt(user_verified); dest.writeInt(aggr_type); dest.writeInt(cell_type); dest.writeInt(article_sub_type); dest.writeInt(bury_count); dest.writeString(title); dest.writeInt(ignore_web_transform); dest.writeInt(source_icon_style); dest.writeInt(tip); dest.writeInt(hot); dest.writeString(share_url); dest.writeInt(has_mp4_video); dest.writeString(source); dest.writeInt(comment_count); dest.writeString(article_url); dest.writeInt(share_count); dest.writeString(stick_label); dest.writeInt(publish_time); dest.writeByte((byte) (has_image ? 1 : 0)); dest.writeInt(cell_layout_style); dest.writeLong(tag_id); dest.writeInt(video_style); dest.writeString(verified_content); dest.writeString(display_url); dest.writeLong(item_id); dest.writeByte((byte) (is_subject ? 1 : 0)); dest.writeInt(stick_style); dest.writeByte((byte) (show_portrait ? 1 : 0)); dest.writeInt(repin_count); dest.writeInt(cell_flag); dest.writeString(source_open_url); dest.writeInt(level); dest.writeInt(digg_count); dest.writeString(behot_time); dest.writeString(article_alt_url); dest.writeLong(cursor); dest.writeString(url); dest.writeInt(preload_web); dest.writeInt(user_repin); dest.writeInt(label_style); dest.writeInt(item_version); dest.writeParcelable(media_info, flags); dest.writeLong(group_id); dest.writeInt(gallary_image_count); dest.writeString(video_id); dest.writeParcelable(video_detail_info, flags); dest.writeInt(video_duration); dest.writeInt(group_flags); dest.writeInt(like_count); } @Override public int describeContents() { return 0; } public LogPbBean getLog_pb() { return log_pb; } public void setLog_pb(LogPbBean log_pb) { this.log_pb = log_pb; } public int getRead_count() { return read_count; } public void setRead_count(int read_count) { this.read_count = read_count; } public String getMedia_name() { return media_name; } public void setMedia_name(String media_name) { this.media_name = media_name; } public int getBan_comment() { return ban_comment; } public void setBan_comment(int ban_comment) { this.ban_comment = ban_comment; } public String getAbstractX() { return abstractX; } public void setAbstractX(String abstractX) { this.abstractX = abstractX; } public int getBan_bury() { return ban_bury; } public void setBan_bury(int ban_bury) { this.ban_bury = ban_bury; } public boolean isHas_video() { return has_video; } public void setHas_video(boolean has_video) { this.has_video = has_video; } public int getArticle_type() { return article_type; } public void setArticle_type(int article_type) { this.article_type = article_type; } public String getTag() { return tag; } public void setTag(String tag) { this.tag = tag; } public ForwardInfoBean getForward_info() { return forward_info; } public void setForward_info(ForwardInfoBean forward_info) { this.forward_info = forward_info; } // public boolean getHas_m3u8_video() { // return has_m3u8_video; // } // public void setHas_m3u8_video(boolean has_m3u8_video) { // this.has_m3u8_video = has_m3u8_video; // } public String getKeywords() { return keywords; } public void setKeywords(String keywords) { this.keywords = keywords; } public String getRid() { return rid; } public void setRid(String rid) { this.rid = rid; } public String getLabel() { return label; } public void setLabel(String label) { this.label = label; } public boolean isShow_portrait_article() { return show_portrait_article; } public void setShow_portrait_article(boolean show_portrait_article) { this.show_portrait_article = show_portrait_article; } public int getUser_verified() { return user_verified; } public void setUser_verified(int user_verified) { this.user_verified = user_verified; } public int getAggr_type() { return aggr_type; } public void setAggr_type(int aggr_type) { this.aggr_type = aggr_type; } public int getCell_type() { return cell_type; } public void setCell_type(int cell_type) { this.cell_type = cell_type; } public int getArticle_sub_type() { return article_sub_type; } public void setArticle_sub_type(int article_sub_type) { this.article_sub_type = article_sub_type; } public int getBury_count() { return bury_count; } public void setBury_count(int bury_count) { this.bury_count = bury_count; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getIgnore_web_transform() { return ignore_web_transform; } public void setIgnore_web_transform(int ignore_web_transform) { this.ignore_web_transform = ignore_web_transform; } public int getSource_icon_style() { return source_icon_style; } public void setSource_icon_style(int source_icon_style) { this.source_icon_style = source_icon_style; } public int getTip() { return tip; } public void setTip(int tip) { this.tip = tip; } public int getHot() { return hot; } public void setHot(int hot) { this.hot = hot; } public String getShare_url() { return share_url; } public void setShare_url(String share_url) { this.share_url = share_url; } public int getHas_mp4_video() { return has_mp4_video; } public void setHas_mp4_video(int has_mp4_video) { this.has_mp4_video = has_mp4_video; } public String getSource() { return source; } public void setSource(String source) { this.source = source; } public int getComment_count() { return comment_count; } public void setComment_count(int comment_count) { this.comment_count = comment_count; } public String getArticle_url() { return article_url; } public void setArticle_url(String article_url) { this.article_url = article_url; } public int getShare_count() { return share_count; } public void setShare_count(int share_count) { this.share_count = share_count; } public String getStick_label() { return stick_label; } public void setStick_label(String stick_label) { this.stick_label = stick_label; } public int getPublish_time() { return publish_time; } public void setPublish_time(int publish_time) { this.publish_time = publish_time; } public boolean isHas_image() { return has_image; } public void setHas_image(boolean has_image) { this.has_image = has_image; } public int getCell_layout_style() { return cell_layout_style; } public void setCell_layout_style(int cell_layout_style) { this.cell_layout_style = cell_layout_style; } public long getTag_id() { return tag_id; } public void setTag_id(long tag_id) { this.tag_id = tag_id; } public int getVideo_style() { return video_style; } public void setVideo_style(int video_style) { this.video_style = video_style; } public String getVerified_content() { return verified_content; } public void setVerified_content(String verified_content) { this.verified_content = verified_content; } public String getDisplay_url() { return display_url; } public void setDisplay_url(String display_url) { this.display_url = display_url; } // public boolean is_stick() { // return is_stick; // } // public void setIs_stick(boolean is_stick) { // this.is_stick = is_stick; // } public long getItem_id() { return item_id; } public void setItem_id(long item_id) { this.item_id = item_id; } public boolean is_subject() { return is_subject; } public void setIs_subject(boolean is_subject) { this.is_subject = is_subject; } public int getStick_style() { return stick_style; } public void setStick_style(int stick_style) { this.stick_style = stick_style; } public boolean isShow_portrait() { return show_portrait; } public void setShow_portrait(boolean show_portrait) { this.show_portrait = show_portrait; } public int getRepin_count() { return repin_count; } public void setRepin_count(int repin_count) { this.repin_count = repin_count; } public int getCell_flag() { return cell_flag; } public void setCell_flag(int cell_flag) { this.cell_flag = cell_flag; } public UserInfoBean getUser_info() { return user_info; } public void setUser_info(UserInfoBean user_info) { this.user_info = user_info; } public String getSource_open_url() { return source_open_url; } public void setSource_open_url(String source_open_url) { this.source_open_url = source_open_url; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public int getDigg_count() { return digg_count; } public void setDigg_count(int digg_count) { this.digg_count = digg_count; } public String getBehot_time() { return behot_time; } public void setBehot_time(String behot_time) { this.behot_time = behot_time; } public String getArticle_alt_url() { return article_alt_url; } public void setArticle_alt_url(String article_alt_url) { this.article_alt_url = article_alt_url; } public long getCursor() { return cursor; } public void setCursor(long cursor) { this.cursor = cursor; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getPreload_web() { return preload_web; } public void setPreload_web(int preload_web) { this.preload_web = preload_web; } public int getUser_repin() { return user_repin; } public void setUser_repin(int user_repin) { this.user_repin = user_repin; } public int getLabel_style() { return label_style; } public void setLabel_style(int label_style) { this.label_style = label_style; } public int getItem_version() { return item_version; } public void setItem_version(int item_version) { this.item_version = item_version; } public MediaInfoBean getMedia_info() { return media_info; } public void setMedia_info(MediaInfoBean media_info) { this.media_info = media_info; } public long getGroup_id() { return group_id; } public void setGroup_id(long group_id) { this.group_id = group_id; } public MiddleImageBean getMiddle_image() { return middle_image; } public void setMiddle_image(MiddleImageBean middle_image) { this.middle_image = middle_image; } public int getGallary_image_count() { return gallary_image_count; } public void setGallary_image_count(int gallary_image_count) { this.gallary_image_count = gallary_image_count; } public List<ImageListBean> getImage_list() { return image_list; } public void setImage_list(List<ImageListBean> image_list) { this.image_list = image_list; } public String getVideo_id() { return video_id; } public void setVideo_id(String video_id) { this.video_id = video_id; } public VideoDetailInfoBean getVideo_detail_info() { return video_detail_info; } public void setVideo_detail_info(VideoDetailInfoBean video_detail_info) { this.video_detail_info = video_detail_info; } public int getVideo_duration() { return video_duration; } public void setVideo_duration(int video_duration) { this.video_duration = video_duration; } public int getGroup_flags() { return group_flags; } public void setGroup_flags(int group_flags) { this.group_flags = group_flags; } public int getLike_count() { return like_count; } public void setLike_count(int like_count) { this.like_count = like_count; } @Override public String toString() { return "MultiNewsArticleDataBean{" + "log_pb=" + log_pb + ", read_count=" + read_count + ", media_name='" + media_name + '\'' + ", ban_comment=" + ban_comment + ", abstractX='" + abstractX + '\'' + ", ban_bury=" + ban_bury + ", has_video=" + has_video + ", article_type=" + article_type + ", tag='" + tag + '\'' + ", forward_info=" + forward_info + // ", has_m3u8_video=" + has_m3u8_video + ", keywords='" + keywords + '\'' + ", rid='" + rid + '\'' + ", label='" + label + '\'' + ", show_portrait_article=" + show_portrait_article + ", user_verified=" + user_verified + ", aggr_type=" + aggr_type + ", cell_type=" + cell_type + ", article_sub_type=" + article_sub_type + ", bury_count=" + bury_count + ", title='" + title + '\'' + ", ignore_web_transform=" + ignore_web_transform + ", source_icon_style=" + source_icon_style + ", tip=" + tip + ", hot=" + hot + ", share_url='" + share_url + '\'' + ", has_mp4_video=" + has_mp4_video + ", source='" + source + '\'' + ", comment_count=" + comment_count + ", article_url='" + article_url + '\'' + ", share_count=" + share_count + ", stick_label='" + stick_label + '\'' + ", publish_time=" + publish_time + ", has_image=" + has_image + ", cell_layout_style=" + cell_layout_style + ", tag_id=" + tag_id + ", video_style=" + video_style + ", verified_content='" + verified_content + '\'' + ", display_url='" + display_url + '\'' + ", item_id=" + item_id + ", is_subject=" + is_subject + ", stick_style=" + stick_style + ", show_portrait=" + show_portrait + ", repin_count=" + repin_count + ", cell_flag=" + cell_flag + ", user_info=" + user_info + ", source_open_url='" + source_open_url + '\'' + ", level=" + level + ", digg_count=" + digg_count + ", behot_time='" + behot_time + '\'' + ", article_alt_url='" + article_alt_url + '\'' + ", cursor=" + cursor + ", url='" + url + '\'' + ", preload_web=" + preload_web + ", user_repin=" + user_repin + ", label_style=" + label_style + ", item_version=" + item_version + ", media_info=" + media_info + ", group_id=" + group_id + ", middle_image=" + middle_image + ", gallary_image_count=" + gallary_image_count + ", video_id='" + video_id + '\'' + ", video_detail_info=" + video_detail_info + ", video_duration=" + video_duration + ", group_flags=" + group_flags + ", like_count=" + like_count + ", image_list=" + image_list + '}'; } public static class LogPbBean { /** * impr_id : 20170519112306010003048108480AA6 */ private String impr_id; public String getImpr_id() { return impr_id; } public void setImpr_id(String impr_id) { this.impr_id = impr_id; } } public static class ForwardInfoBean { /** * forward_count : 8 */ private int forward_count; public int getForward_count() { return forward_count; } public void setForward_count(int forward_count) { this.forward_count = forward_count; } } public static class UserInfoBean { /** * verified_content : * avatar_url : http://p3.pstatp.com/thumb/ca400072481685ad43b * user_id : 50502346173 * name : 人民网 * follower_count : 0 * follow : false * user_auth_info : * user_verified : false * description : */ private String verified_content; private String avatar_url; private long user_id; private String name; private int follower_count; private boolean follow; private String user_auth_info; private boolean user_verified; private String description; public String getVerified_content() { return verified_content; } public void setVerified_content(String verified_content) { this.verified_content = verified_content; } public String getAvatar_url() { return avatar_url; } public void setAvatar_url(String avatar_url) { this.avatar_url = avatar_url; } public long getUser_id() { return user_id; } public void setUser_id(long user_id) { this.user_id = user_id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getFollower_count() { return follower_count; } public void setFollower_count(int follower_count) { this.follower_count = follower_count; } public boolean isFollow() { return follow; } public void setFollow(boolean follow) { this.follow = follow; } public String getUser_auth_info() { return user_auth_info; } public void setUser_auth_info(String user_auth_info) { this.user_auth_info = user_auth_info; } public boolean isUser_verified() { return user_verified; } public void setUser_verified(boolean user_verified) { this.user_verified = user_verified; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } } public static class MediaInfoBean implements Parcelable { public static final Creator<MediaInfoBean> CREATOR = new Creator<MediaInfoBean>() { @Override public MediaInfoBean createFromParcel(Parcel in) { return new MediaInfoBean(in); } @Override public MediaInfoBean[] newArray(int size) { return new MediaInfoBean[size]; } }; /** * user_id : 50502346173 * verified_content : * avatar_url : http://p3.pstatp.com/large/ca400072481685ad43b * media_id : 50502346173 * name : 人民网 * recommend_type : 0 * follow : false * recommend_reason : * is_star_user : false * user_verified : false */ private long user_id; private String verified_content; private String avatar_url; private String media_id; private String name; private int recommend_type; private boolean follow; private String recommend_reason; private boolean is_star_user; private boolean user_verified; public MediaInfoBean() { } protected MediaInfoBean(Parcel in) { user_id = in.readLong(); verified_content = in.readString(); avatar_url = in.readString(); media_id = in.readString(); name = in.readString(); recommend_type = in.readInt(); follow = in.readByte() != 0; recommend_reason = in.readString(); is_star_user = in.readByte() != 0; user_verified = in.readByte() != 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(user_id); dest.writeString(verified_content); dest.writeString(avatar_url); dest.writeString(media_id); dest.writeString(name); dest.writeInt(recommend_type); dest.writeByte((byte) (follow ? 1 : 0)); dest.writeString(recommend_reason); dest.writeByte((byte) (is_star_user ? 1 : 0)); dest.writeByte((byte) (user_verified ? 1 : 0)); } @Override public int describeContents() { return 0; } public long getUser_id() { return user_id; } public void setUser_id(long user_id) { this.user_id = user_id; } public String getVerified_content() { return verified_content; } public void setVerified_content(String verified_content) { this.verified_content = verified_content; } public String getAvatar_url() { return avatar_url; } public void setAvatar_url(String avatar_url) { this.avatar_url = avatar_url; } public String getMedia_id() { return media_id; } public void setMedia_id(String media_id) { this.media_id = media_id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getRecommend_type() { return recommend_type; } public void setRecommend_type(int recommend_type) { this.recommend_type = recommend_type; } public boolean isFollow() { return follow; } public void setFollow(boolean follow) { this.follow = follow; } public String getRecommend_reason() { return recommend_reason; } public void setRecommend_reason(String recommend_reason) { this.recommend_reason = recommend_reason; } public boolean isIs_star_user() { return is_star_user; } public void setIs_star_user(boolean is_star_user) { this.is_star_user = is_star_user; } public boolean isUser_verified() { return user_verified; } public void setUser_verified(boolean user_verified) { this.user_verified = user_verified; } } public static class MiddleImageBean { /** * url : http://p9.pstatp.com/list/300x196/207c000e549a17910c1c.webp * width : 400 * url_list : [{"url":"http://p9.pstatp.com/list/300x196/207c000e549a17910c1c.webp"},{"url":"http://pb1.pstatp.com/list/300x196/207c000e549a17910c1c.webp"},{"url":"http://pb3.pstatp.com/list/300x196/207c000e549a17910c1c.webp"}] * uri : list/207c000e549a17910c1c * height : 225 */ private String url; private int width; private String uri; private int height; private List<UrlListBean> url_list; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public List<UrlListBean> getUrl_list() { return url_list; } public void setUrl_list(List<UrlListBean> url_list) { this.url_list = url_list; } public static class UrlListBean { /** * url : http://p9.pstatp.com/list/300x196/207c000e549a17910c1c.webp */ private String url; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } } } public static class VideoDetailInfoBean implements Parcelable { public static final Creator<VideoDetailInfoBean> CREATOR = new Creator<VideoDetailInfoBean>() { @Override public VideoDetailInfoBean createFromParcel(Parcel in) { return new VideoDetailInfoBean(in); } @Override public VideoDetailInfoBean[] newArray(int size) { return new VideoDetailInfoBean[size]; } }; /** * group_flags : 32832 * video_type : 0 * video_preloading_flag : 1 * video_url : [] * direct_play : 1 * detail_video_large_image : {"url":"http://p3.pstatp.com/video1609/17600009fb1bb36ce3ee","width":580,"url_list":[{"url":"http://p3.pstatp.com/video1609/17600009fb1bb36ce3ee"},{"url":"http://pb9.pstatp.com/video1609/17600009fb1bb36ce3ee"},{"url":"http://pb1.pstatp.com/video1609/17600009fb1bb36ce3ee"}],"uri":"video1609/17600009fb1bb36ce3ee","height":326} * show_pgc_subscribe : 1 * video_third_monitor_url : * video_id : d4715d18819e4acc8b3012374dd4588f * video_watching_count : 0 * video_watch_count : 3502527 */ private int group_flags; private int video_type; private int video_preloading_flag; private int direct_play; private DetailVideoLargeImageBean detail_video_large_image; private int show_pgc_subscribe; private String video_third_monitor_url; private String video_id; private int video_watching_count; private int video_watch_count; private List<?> video_url; public VideoDetailInfoBean(Parcel in) { group_flags = in.readInt(); video_type = in.readInt(); video_preloading_flag = in.readInt(); direct_play = in.readInt(); detail_video_large_image = in.readParcelable(DetailVideoLargeImageBean.class.getClassLoader()); show_pgc_subscribe = in.readInt(); video_third_monitor_url = in.readString(); video_id = in.readString(); video_watching_count = in.readInt(); video_watch_count = in.readInt(); } public VideoDetailInfoBean() { } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(group_flags); dest.writeInt(video_type); dest.writeInt(video_preloading_flag); dest.writeInt(direct_play); dest.writeParcelable(detail_video_large_image, flags); dest.writeInt(show_pgc_subscribe); dest.writeString(video_third_monitor_url); dest.writeString(video_id); dest.writeInt(video_watching_count); dest.writeInt(video_watch_count); } @Override public int describeContents() { return 0; } public int getGroup_flags() { return group_flags; } public void setGroup_flags(int group_flags) { this.group_flags = group_flags; } public int getVideo_type() { return video_type; } public void setVideo_type(int video_type) { this.video_type = video_type; } public int getVideo_preloading_flag() { return video_preloading_flag; } public void setVideo_preloading_flag(int video_preloading_flag) { this.video_preloading_flag = video_preloading_flag; } public int getDirect_play() { return direct_play; } public void setDirect_play(int direct_play) { this.direct_play = direct_play; } public DetailVideoLargeImageBean getDetail_video_large_image() { return detail_video_large_image; } public void setDetail_video_large_image(DetailVideoLargeImageBean detail_video_large_image) { this.detail_video_large_image = detail_video_large_image; } public int getShow_pgc_subscribe() { return show_pgc_subscribe; } public void setShow_pgc_subscribe(int show_pgc_subscribe) { this.show_pgc_subscribe = show_pgc_subscribe; } public String getVideo_third_monitor_url() { return video_third_monitor_url; } public void setVideo_third_monitor_url(String video_third_monitor_url) { this.video_third_monitor_url = video_third_monitor_url; } public String getVideo_id() { return video_id; } public void setVideo_id(String video_id) { this.video_id = video_id; } public int getVideo_watching_count() { return video_watching_count; } public void setVideo_watching_count(int video_watching_count) { this.video_watching_count = video_watching_count; } public int getVideo_watch_count() { return video_watch_count; } public void setVideo_watch_count(int video_watch_count) { this.video_watch_count = video_watch_count; } public List<?> getVideo_url() { return video_url; } public void setVideo_url(List<?> video_url) { this.video_url = video_url; } public static class DetailVideoLargeImageBean implements Parcelable { public static final Creator<DetailVideoLargeImageBean> CREATOR = new Creator<DetailVideoLargeImageBean>() { @Override public DetailVideoLargeImageBean createFromParcel(Parcel in) { return new DetailVideoLargeImageBean(in); } @Override public DetailVideoLargeImageBean[] newArray(int size) { return new DetailVideoLargeImageBean[size]; } }; /** * url : http://p3.pstatp.com/video1609/17600009fb1bb36ce3ee * width : 580 * url_list : [{"url":"http://p3.pstatp.com/video1609/17600009fb1bb36ce3ee"},{"url":"http://pb9.pstatp.com/video1609/17600009fb1bb36ce3ee"},{"url":"http://pb1.pstatp.com/video1609/17600009fb1bb36ce3ee"}] * uri : video1609/17600009fb1bb36ce3ee * height : 326 */ private String url; private int width; private String uri; private int height; private List<MiddleImageBean> url_list; public DetailVideoLargeImageBean(Parcel in) { url = in.readString(); width = in.readInt(); uri = in.readString(); height = in.readInt(); } public DetailVideoLargeImageBean() { } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(url); dest.writeInt(width); dest.writeString(uri); dest.writeInt(height); } @Override public int describeContents() { return 0; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public List<MiddleImageBean> getUrl_list() { return url_list; } public void setUrl_list(List<MiddleImageBean> url_list) { this.url_list = url_list; } } } public static class LargeImageListBean { /** * url : http://p3.pstatp.com/video1609/17600009fb1bb36ce3ee * width : 580 * url_list : [{"url":"http://p3.pstatp.com/video1609/17600009fb1bb36ce3ee"},{"url":"http://pb9.pstatp.com/video1609/17600009fb1bb36ce3ee"},{"url":"http://pb1.pstatp.com/video1609/17600009fb1bb36ce3ee"}] * uri : video1609/17600009fb1bb36ce3ee * height : 326 */ @SerializedName("url") private String urlX; private int width; private String uri; private int height; private List<MiddleImageBean> url_list; public String getUrlX() { return urlX; } public void setUrlX(String urlX) { this.urlX = urlX; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public List<MiddleImageBean> getUrl_list() { return url_list; } public void setUrl_list(List<MiddleImageBean> url_list) { this.url_list = url_list; } } public static class ImageListBean { /** * url : http://p1.pstatp.com/list/300x196/213b0003f2d1a191e4ff.webp * width : 496 * url_list : [{"url":"http://p1.pstatp.com/list/300x196/213b0003f2d1a191e4ff.webp"},{"url":"http://pb3.pstatp.com/list/300x196/213b0003f2d1a191e4ff.webp"},{"url":"http://pb9.pstatp.com/list/300x196/213b0003f2d1a191e4ff.webp"}] * uri : list/213b0003f2d1a191e4ff * height : 279 */ @SerializedName("url") private String url; private int width; private String uri; private int height; private List<LargeImageListBean> url_list; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public List<LargeImageListBean> getUrl_list() { return url_list; } public void setUrl_list(List<LargeImageListBean> url_list) { this.url_list = url_list; } } }
比较庞大,有1600多行。
3.构建API请求
3.1.封装API请求接口(整体)
public interface IMobileNewsApi { String HOST = "http://is.snssdk.com/"; /** * 获取个性化新闻 * 深圳 http://is.snssdk.com/api/news/feed/v58/?iid=5034850950&device_id=6096495334&category=news_society * 深圳 http://lf.snssdk.com/api/news/feed/v58/?iid=12507202490&device_id=37487219424&category=news_society * 天津 http://ib.snssdk.com/api/news/feed/v58/? * 北京 http://iu.snssdk.com/api/news/feed/v58/? * * @param iid 用户ID * @param deviceId 设备ID * @param category 新闻/图片/视频栏目 */ @GET("http://is.snssdk.com/api/news/feed/v58/") Call<ResponseBody> getNewsArticle( @Query("iid") String iid, @Query("device_id") String deviceId, @Query("category") String category); @GET("http://is.snssdk.com/api/news/feed/v62/?iid=5034850950&device_id=6096495334&refer=1&count=20&aid=13") Observable<MultiNewsArticleBean> getNewsArticle( @Query("category") String category, @Query("max_behot_time") String maxBehotTime); @GET("http://lf.snssdk.com/api/news/feed/v62/?iid=12507202490&device_id=37487219424&refer=1&count=20&aid=13") Observable<MultiNewsArticleBean> getNewsArticle2( @Query("category") String category, @Query("max_behot_time") String maxBehotTime); /** * 获取新闻评论 * 按热度排序 * http://is.snssdk.com/article/v53/tab_comments/?group_id=6314103921648926977&offset=0&tab_index=0 * 按时间排序 * http://is.snssdk.com/article/v53/tab_comments/?group_id=6314103921648926977&offset=0&tab_index=1 * * @param groupId 新闻ID * @param offset 偏移量 */ @GET("http://is.snssdk.com/article/v53/tab_comments/") Observable<NewsCommentBean> getNewsComment( @Query("group_id") String groupId, @Query("offset") int offset); }
3.2.传递两个参数返回Observable<MultiNewsArticleBean>类型第一种(局部)
@GET("http://is.snssdk.com/api/news/feed/v62/?iid=5034850950&device_id=6096495334&refer=1&count=20&aid=13") Observable<MultiNewsArticleBean> getNewsArticle( @Query("category") String category, @Query("max_behot_time") String maxBehotTime);
3.3.传递两个参数返回Observable<MultiNewsArticleBean>类型第二种(局部)
@GET("http://lf.snssdk.com/api/news/feed/v62/?iid=12507202490&device_id=37487219424&refer=1&count=20&aid=13") Observable<MultiNewsArticleBean> getNewsArticle2( @Query("category") String category, @Query("max_behot_time") String maxBehotTime);
4.通用文章片段的实现
4.1.新闻文章基础接口
public interface INewsArticle { interface View extends IBaseListView<Presenter>{ void onLoadData(); void onRefresh(); } interface Presenter extends IBasePresenter{ void doLoadData(String... category); void doLoadMoreData(); void doSetAdapter(List<MultiNewsArticleDataBean> dataBean); void doShowNoMore(); } }
4.2.新闻文章的处理器presenter类
主要处理API的请求数据,加载更多,处理刷新,处理网络错误等。
package com.jasonjan.headnews.module.news.article; import android.text.TextUtils; import com.google.gson.Gson; import com.jasonjan.headnews.api.IMobileNewsApi; import com.jasonjan.headnews.bean.news.MultiNewsArticleBean; import com.jasonjan.headnews.bean.news.MultiNewsArticleDataBean; import com.jasonjan.headnews.main.ErrorAction; import com.jasonjan.headnews.main.RetrofitFactory; import com.jasonjan.headnews.util.TimeUtil; import java.util.ArrayList; import java.util.List; import java.util.Random; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.annotations.NonNull; import io.reactivex.functions.Consumer; import io.reactivex.functions.Function; import io.reactivex.functions.Predicate; import io.reactivex.schedulers.Schedulers; /** * Created by JasonJan on 2017/12/12. */ public class NewsArticlePresenter implements INewsArticle.Presenter { private static final String TAG = "NewsArticlePresenter"; private INewsArticle.View view; private List<MultiNewsArticleDataBean> dataList = new ArrayList<>(); private String category; private String time; private Gson gson = new Gson(); private Random random = new Random(); public NewsArticlePresenter(INewsArticle.View view) { this.view = view; this.time = TimeUtil.getCurrentTimeStamp(); } @Override public void doLoadData(String... category){ try { if (this.category == null) { this.category = category[0]; } } catch (Exception e) { ErrorAction.print(e); } // 释放内存 if (dataList.size() > 150) { dataList.clear(); } getRandom() .subscribeOn(Schedulers.io()) .switchMap(new Function<MultiNewsArticleBean, Observable<MultiNewsArticleDataBean>>() { @Override public Observable<MultiNewsArticleDataBean> apply(@NonNull MultiNewsArticleBean multiNewsArticleBean) throws Exception { List<MultiNewsArticleDataBean> dataList = new ArrayList<>(); for (MultiNewsArticleBean.DataBean dataBean : multiNewsArticleBean.getData()) { dataList.add(gson.fromJson(dataBean.getContent(), MultiNewsArticleDataBean.class)); } return Observable.fromIterable(dataList); } }) .filter(new Predicate<MultiNewsArticleDataBean>() { @Override public boolean test(@NonNull MultiNewsArticleDataBean dataBean) throws Exception { time = dataBean.getBehot_time(); if (TextUtils.isEmpty(dataBean.getSource())) { return false; } try { // 过滤头条问答新闻 if (dataBean.getSource().contains("头条问答") || dataBean.getTag().contains("ad") || dataBean.getSource().contains("悟空问答")) { return false; } // 过滤头条问答新闻 if (dataBean.getRead_count() == 0 || TextUtils.isEmpty(dataBean.getMedia_name())) { String title = dataBean.getTitle(); if (title.lastIndexOf("?") == title.length() - 1) { return false; } } } catch (NullPointerException e) { ErrorAction.print(e); } // 过滤重复新闻(与上次刷新的数据比较) for (MultiNewsArticleDataBean bean : dataList) { if (bean.getTitle().equals(dataBean.getTitle())) { return false; } } return true; } }) .toList() .map(new Function<List<MultiNewsArticleDataBean>, List<MultiNewsArticleDataBean>>() { @Override public List<MultiNewsArticleDataBean> apply(@NonNull List<MultiNewsArticleDataBean> list) throws Exception { // 过滤重复新闻(与本次刷新的数据比较,因为使用了2个请求,数据会有重复) for (int i = 0; i < list.size() - 1; i++) { for (int j = list.size() - 1; j > i; j--) { if (list.get(j).getTitle().equals(list.get(i).getTitle())) { list.remove(j); } } } return list; } }) .compose(view.<List<MultiNewsArticleDataBean>>bindToLife()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<List<MultiNewsArticleDataBean>>() { @Override public void accept(@NonNull List<MultiNewsArticleDataBean> list) throws Exception { if (null != list && list.size() > 0) { doSetAdapter(list); } else { doShowNoMore(); } } }, new Consumer<Throwable>() { @Override public void accept(@NonNull Throwable throwable) throws Exception { doShowNetError(); ErrorAction.print(throwable); } }); } @Override public void doLoadMoreData() { doLoadData(); } @Override public void doSetAdapter(List<MultiNewsArticleDataBean> list) { dataList.addAll(list); view.onSetAdapter(dataList); view.onHideLoading(); } @Override public void doRefresh() { if (dataList.size() != 0) { dataList.clear(); time = TimeUtil.getCurrentTimeStamp(); } view.onShowLoading(); doLoadData(); } @Override public void doShowNetError() { view.onHideLoading(); view.onShowNetError(); } @Override public void doShowNoMore() { view.onHideLoading(); view.onShowNoMore(); } private Observable<MultiNewsArticleBean> getRandom() { int i = random.nextInt(10); if (i % 2 == 0) { Observable<MultiNewsArticleBean> ob1 = RetrofitFactory.getRetrofit().create(IMobileNewsApi.class) .getNewsArticle(this.category, this.time); return ob1; } else { Observable<MultiNewsArticleBean> ob2 = RetrofitFactory.getRetrofit().create(IMobileNewsApi.class) .getNewsArticle2(this.category, this.time); return ob2; } } }
4.3.新闻文章的视图片段
继承了BaseListFragment,传递了接口中的处理器
package com.jasonjan.headnews.module.news.article; import android.os.Bundle; import android.view.View; import com.jasonjan.headnews.adapter.DiffCallback; import com.jasonjan.headnews.bean.common.LoadingBean; import com.jasonjan.headnews.main.Register; import com.jasonjan.headnews.module.base.BaseListFragment; import com.jasonjan.headnews.util.OnLoadMoreListener; import java.util.List; import me.drakeet.multitype.Items; import me.drakeet.multitype.MultiTypeAdapter; /** * Created by JasonJan on 2017/12/12. */ public class NewsArticleView extends BaseListFragment<INewsArticle.Presenter> implements INewsArticle.View { private static final String TAG = "NewsArticleView"; private String categoryId; public static NewsArticleView newInstance(String categoryId) { Bundle bundle = new Bundle(); bundle.putString(TAG, categoryId); NewsArticleView view = new NewsArticleView(); view.setArguments(bundle); return view; } @Override protected void initData() { categoryId = getArguments().getString(TAG); } @Override protected void initView(View view) { super.initView(view); adapter = new MultiTypeAdapter(oldItems); Register.registerNewsArticleItem(adapter); recyclerView.setAdapter(adapter); recyclerView.addOnScrollListener(new OnLoadMoreListener() { @Override public void onLoadMore() { if (canLoadMore) { canLoadMore = false; presenter.doLoadMoreData(); } } }); } @Override public void fetchData() { super.fetchData(); onLoadData(); } @Override public void onLoadData() { onShowLoading(); presenter.doLoadData(categoryId); } @Override public void onSetAdapter(final List<?> list) { Items newItems = new Items(list); newItems.add(new LoadingBean()); DiffCallback.notifyDataSetChanged(oldItems, newItems, DiffCallback.MUlTI_NEWS, adapter); oldItems.clear(); oldItems.addAll(newItems); canLoadMore = true; } @Override public void setPresenter(INewsArticle.Presenter presenter) { if (null == presenter) { this.presenter = new NewsArticlePresenter(this); } } }
4.4.自定义Register添加类型==>注册数据类型
public static void registerNewsArticleItem(@NonNull MultiTypeAdapter adapter) { // 一个类型对应多个 ItemViewBinder adapter.register(MultiNewsArticleDataBean.class) .to(new NewsArticleImgViewBinder(), new NewsArticleVideoViewBinder(), new NewsArticleTextViewBinder()) .withClassLinker(new ClassLinker<MultiNewsArticleDataBean>() { @NonNull @Override public Class<? extends ItemViewBinder<MultiNewsArticleDataBean, ?>> index(@NonNull MultiNewsArticleDataBean item) { if (item.isHas_video()) { return NewsArticleVideoViewBinder.class; } if (null != item.getImage_list() && item.getImage_list().size() > 0) { return NewsArticleImgViewBinder.class; } return NewsArticleTextViewBinder.class; } }); adapter.register(LoadingBean.class, new LoadingViewBinder()); adapter.register(LoadingEndBean.class, new LoadingEndViewBinder()); }
有三种类型,一种是视频型,一种图片型,一种文字型。
后面要写这三个视图绑定类。
4.5.自定义Diffback添加类型==>判断新老数据是否相同
在areItemsTheSame函数中添加这种类型:
case MUlTI_NEWS: return ((MultiNewsArticleDataBean) oldList.get(oldItemPosition)).getTitle().equals( ((MultiNewsArticleDataBean) newList.get(newItemPosition)).getTitle());
在areContentsTheSame函数中添加这种类型:
case MUlTI_NEWS: return ((MultiNewsArticleDataBean) oldList.get(oldItemPosition)).getItem_id() == ((MultiNewsArticleDataBean) newList.get(newItemPosition)).getItem_id();
5.三种类型的视图绑定
5.1.视频类型的页面布局
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView 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="wrap_content" android:layout_marginBottom="4dp" android:layout_marginTop="4dp" android:background="@color/viewBackground" app:cardElevation="1dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" android:foreground="?attr/selectableItemBackground" android:padding="16dp"> <LinearLayout android:id="@+id/header" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <com.jasonjan.headnews.widget.CircleImageView android:id="@+id/iv_media" android:layout_width="22dp" android:layout_height="22dp" android:scaleType="centerCrop"/> <TextView android:id="@+id/tv_extra" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginStart="8dp" android:ellipsize="end" android:maxLength="30" android:maxLines="1" android:textAppearance="@style/TextAppearance.AppCompat.Caption" tools:text="新闻源 - 2222条评论 - 1小时前"/> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/iv_dots" android:layout_width="22dp" android:layout_height="22dp" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:padding="4dp" android:scaleType="center" app:srcCompat="@drawable/ic_dots_horizontal_grey500_24dp" tools:ignore="ContentDescription"/> </RelativeLayout> </LinearLayout> <LinearLayout android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/header" android:layout_marginTop="4dp" android:orientation="vertical"> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="2" android:textStyle="bold" tools:text="菲总统称中国将向菲提供武器 已指示军方前往接收"/> <RelativeLayout android:layout_width="match_parent" android:layout_height="169dp" android:paddingTop="8dp"> <ImageView android:id="@+id/iv_video_image" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:src="@color/viewBackground" tools:ignore="ContentDescription"/> <TextView android:id="@+id/tv_video_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_marginBottom="8dp" android:layout_marginEnd="8dp" android:layout_marginRight="8dp" android:background="@color/textColorPrimary" android:padding="2dp" android:textColor="@color/White" tools:text="10:34"/> </RelativeLayout> </LinearLayout> </RelativeLayout> </android.support.v7.widget.CardView>
图片预览:
5.2.视频类型的绑定类
package com.jasonjan.headnews.binder.news; import android.content.Context; import android.support.annotation.NonNull; import android.support.v7.widget.PopupMenu; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.jakewharton.rxbinding2.view.RxView; import com.jasonjan.headnews.R; import com.jasonjan.headnews.bean.news.MultiNewsArticleDataBean; import com.jasonjan.headnews.main.ErrorAction; import com.jasonjan.headnews.main.IntentAction; import com.jasonjan.headnews.util.ImageLoader; import com.jasonjan.headnews.util.SettingUtil; import com.jasonjan.headnews.util.TimeUtil; import com.jasonjan.headnews.widget.CircleImageView; import java.util.concurrent.TimeUnit; import io.reactivex.functions.Consumer; import me.drakeet.multitype.ItemViewBinder; /** * Created by JasonJan on 2017/12/12. */ public class NewsArticleVideoViewBinder extends ItemViewBinder<MultiNewsArticleDataBean,NewsArticleVideoViewBinder.ViewHolder> { private static final String TAG = "NewsArticleHasVideoView"; @NonNull @Override protected NewsArticleVideoViewBinder.ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { View view = inflater.inflate(R.layout.item_news_article_video, parent, false); return new ViewHolder(view); } @Override protected void onBindViewHolder(@NonNull final NewsArticleVideoViewBinder.ViewHolder holder, @NonNull final MultiNewsArticleDataBean item) { final Context context = holder.itemView.getContext(); try { if (null != item.getVideo_detail_info()) { if (null != item.getVideo_detail_info().getDetail_video_large_image()) { String image = item.getVideo_detail_info().getDetail_video_large_image().getUrl(); if (!TextUtils.isEmpty(image)) { ImageLoader.loadCenterCrop(context, image, holder.iv_video_image, R.color.viewBackground, R.mipmap.error_image); } } } else { holder.iv_video_image.setImageResource(R.mipmap.error_image); } if (null != item.getUser_info()) { String avatar_url = item.getUser_info().getAvatar_url(); if (!TextUtils.isEmpty(avatar_url)) { ImageLoader.loadCenterCrop(context, avatar_url, holder.iv_media, R.color.viewBackground); } } String tv_title = item.getTitle(); holder.tv_title.setTextSize(SettingUtil.getInstance().getTextSize()); String tv_source = item.getSource(); String tv_comment_count = item.getComment_count() + "评论"; String tv_datetime = item.getBehot_time() + ""; if (!TextUtils.isEmpty(tv_datetime)) { tv_datetime = TimeUtil.getTimeStampAgo(tv_datetime); } int video_duration = item.getVideo_duration(); String min = String.valueOf(video_duration / 60); String second = String.valueOf(video_duration % 10); if (Integer.parseInt(second) < 10) { second = "0" + second; } String tv_video_time = min + ":" + second; holder.tv_title.setText(tv_title); holder.tv_extra.setText(tv_source + " - " + tv_comment_count + " - " + tv_datetime); holder.tv_video_time.setText(tv_video_time); holder.iv_dots.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { PopupMenu popupMenu = new PopupMenu(context, holder.iv_dots, Gravity.END, 0, R.style.MyPopupMenu); popupMenu.inflate(R.menu.menu_share); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menu) { int itemId = menu.getItemId(); if (itemId == R.id.action_share) { IntentAction.send(context, item.getTitle() + "\n" + item.getShare_url()); } return false; } }); popupMenu.show(); } }); RxView.clicks(holder.itemView) .throttleFirst(1, TimeUnit.SECONDS) .subscribe(new Consumer<Object>() { @Override public void accept(@io.reactivex.annotations.NonNull Object o) throws Exception { // VideoContentActivity.launch(item); } }); } catch (Exception e) { ErrorAction.print(e); } } class ViewHolder extends RecyclerView.ViewHolder { private CircleImageView iv_media; private TextView tv_extra; private TextView tv_title; private ImageView iv_video_image; private TextView tv_video_time; private ImageView iv_dots; ViewHolder(View itemView) { super(itemView); this.iv_media = itemView.findViewById(R.id.iv_media); this.tv_extra = itemView.findViewById(R.id.tv_extra); this.tv_title = itemView.findViewById(R.id.tv_title); this.iv_video_image = itemView.findViewById(R.id.iv_video_image); this.tv_video_time = itemView.findViewById(R.id.tv_video_time); this.iv_dots = itemView.findViewById(R.id.iv_dots); } } }
5.3.图片类型的页面布局
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView 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="wrap_content" android:layout_marginBottom="4dp" android:layout_marginTop="4dp" android:background="@color/viewBackground" app:cardElevation="1dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" android:foreground="?attr/selectableItemBackground" android:padding="16dp"> <LinearLayout android:id="@+id/header" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <com.meiji.toutiao.widget.CircleImageView android:id="@+id/iv_media" android:layout_width="22dp" android:layout_height="22dp" android:scaleType="centerCrop"/> <TextView android:id="@+id/tv_extra" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginStart="8dp" android:ellipsize="end" android:maxLength="30" android:maxLines="1" android:textAppearance="@style/TextAppearance.AppCompat.Caption" tools:text="新闻源 - 2222条评论 - 1小时前"/> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/iv_dots" android:layout_width="22dp" android:layout_height="22dp" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:padding="4dp" android:scaleType="center" app:srcCompat="@drawable/ic_dots_horizontal_grey500_24dp" tools:ignore="ContentDescription"/> </RelativeLayout> </LinearLayout> <LinearLayout android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/header" android:layout_marginTop="4dp"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginRight="8dp" android:layout_weight="1" android:orientation="vertical"> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="2" android:textStyle="bold" tools:text="菲总统称中国将向菲提供武器 已指示军方前往接收"/> <TextView android:id="@+id/tv_abstract" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:ellipsize="end" android:maxLines="3" tools:text="美国总统当选人特朗普日前暗示,可能拿美国的“一中政策”当谈判筹码,与中国大陆就诸如人民币汇率及南海等争议讨价还价。"/> </LinearLayout> <ImageView android:id="@+id/iv_image" android:layout_width="72dp" android:layout_height="72dp" android:layout_marginLeft="8dp" android:layout_marginStart="8dp" tools:ignore="ContentDescription"/> </LinearLayout> </RelativeLayout> </android.support.v7.widget.CardView>
图片预览:
5.4.图片类型的绑定类
package com.jasonjan.headnews.binder.news; import android.content.Context; import android.support.annotation.NonNull; import android.support.v7.widget.PopupMenu; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.jakewharton.rxbinding2.view.RxView; import com.jasonjan.headnews.R; import com.jasonjan.headnews.bean.news.MultiNewsArticleDataBean; import com.jasonjan.headnews.main.ErrorAction; import com.jasonjan.headnews.main.IntentAction; import com.jasonjan.headnews.util.ImageLoader; import com.jasonjan.headnews.util.SettingUtil; import com.jasonjan.headnews.util.TimeUtil; import com.jasonjan.headnews.widget.CircleImageView; import java.util.List; import java.util.concurrent.TimeUnit; import io.reactivex.functions.Consumer; import me.drakeet.multitype.ItemViewBinder; /** * Created by JasonJan on 2017/12/12. */ public class NewsArticleImgViewBinder extends ItemViewBinder<MultiNewsArticleDataBean,NewsArticleImgViewBinder.ViewHolder> { @NonNull @Override protected NewsArticleImgViewBinder.ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { View view = inflater.inflate(R.layout.item_news_article_img, parent, false); return new ViewHolder(view); } @Override protected void onBindViewHolder(@NonNull final NewsArticleImgViewBinder.ViewHolder holder, @NonNull final MultiNewsArticleDataBean item) { final Context context = holder.itemView.getContext(); try { String imgUrl = "http://p3.pstatp.com/"; List<MultiNewsArticleDataBean.ImageListBean> image_list = item.getImage_list(); if (image_list != null && image_list.size() != 0) { String url = image_list.get(0).getUrl(); ImageLoader.loadCenterCrop(context, url, holder.iv_image, R.color.viewBackground); if (!TextUtils.isEmpty(image_list.get(0).getUri())) { imgUrl += image_list.get(0).getUri().replace("list", "large"); } } if (null != item.getUser_info()) { String avatar_url = item.getUser_info().getAvatar_url(); if (!TextUtils.isEmpty(avatar_url)) { ImageLoader.loadCenterCrop(context, avatar_url, holder.iv_media, R.color.viewBackground); } } String tv_title = item.getTitle(); String tv_abstract = item.getAbstractX(); String tv_source = item.getSource(); String tv_comment_count = item.getComment_count() + "评论"; String tv_datetime = item.getBehot_time() + ""; if (!TextUtils.isEmpty(tv_datetime)) { tv_datetime = TimeUtil.getTimeStampAgo(tv_datetime); } holder.tv_title.setText(tv_title); holder.tv_title.setTextSize(SettingUtil.getInstance().getTextSize()); holder.tv_abstract.setText(tv_abstract); holder.tv_extra.setText(tv_source + " - " + tv_comment_count + " - " + tv_datetime); holder.iv_dots.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { PopupMenu popupMenu = new PopupMenu(context, holder.iv_dots, Gravity.END, 0, R.style.MyPopupMenu); popupMenu.inflate(R.menu.menu_share); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menu) { int itemId = menu.getItemId(); if (itemId == R.id.action_share) { IntentAction.send(context, item.getTitle() + "\n" + item.getShare_url()); } return false; } }); popupMenu.show(); } }); final String finalImgUrl = imgUrl; RxView.clicks(holder.itemView) .throttleFirst(1, TimeUnit.SECONDS) .subscribe(new Consumer<Object>() { @Override public void accept(@io.reactivex.annotations.NonNull Object o) throws Exception { //NewsContentActivity.launch(item, finalImgUrl); } }); } catch (Exception e) { ErrorAction.print(e); } } class ViewHolder extends RecyclerView.ViewHolder { private CircleImageView iv_media; private ImageView iv_image; private TextView tv_title; private TextView tv_abstract; private TextView tv_extra; private ImageView iv_dots; ViewHolder(View itemView) { super(itemView); this.iv_media = itemView.findViewById(R.id.iv_media); this.iv_image = itemView.findViewById(R.id.iv_image); this.tv_title = itemView.findViewById(R.id.tv_title); this.tv_abstract = itemView.findViewById(R.id.tv_abstract); this.tv_extra = itemView.findViewById(R.id.tv_extra); this.iv_dots = itemView.findViewById(R.id.iv_dots); } } }
5.5.文字类型的页面布局
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView 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="wrap_content" android:layout_marginBottom="4dp" android:layout_marginTop="4dp" android:background="@color/viewBackground" app:cardElevation="1dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" android:foreground="?attr/selectableItemBackground" android:padding="16dp"> <LinearLayout android:id="@+id/header" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <com.meiji.toutiao.widget.CircleImageView android:id="@+id/iv_media" android:layout_width="22dp" android:layout_height="22dp" android:scaleType="centerCrop"/> <TextView android:id="@+id/tv_extra" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginStart="8dp" android:ellipsize="end" android:maxLength="30" android:maxLines="1" android:textAppearance="@style/TextAppearance.AppCompat.Caption" tools:text="新闻源 - 2222条评论 - 1小时前"/> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/iv_dots" android:layout_width="22dp" android:layout_height="22dp" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:padding="4dp" android:scaleType="center" app:srcCompat="@drawable/ic_dots_horizontal_grey500_24dp" tools:ignore="ContentDescription"/> </RelativeLayout> </LinearLayout> <LinearLayout android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/header" android:layout_marginTop="4dp" android:orientation="vertical"> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="2" android:textStyle="bold" tools:text="菲总统称中国将向菲提供武器 已指示军方前往接收"/> <TextView android:id="@+id/tv_abstract" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:ellipsize="end" android:maxLines="3" tools:text="美国总统当选人特朗普日前暗示,可能拿美国的“一中政策”当谈判筹码,与中国大陆就诸如人民币汇率及南海等争议讨价还价。"/> </LinearLayout> </RelativeLayout> </android.support.v7.widget.CardView>
图片预览:
5.6.文字类型的绑定类
package com.jasonjan.headnews.binder.news; import android.content.Context; import android.support.annotation.NonNull; import android.support.v7.widget.PopupMenu; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.jakewharton.rxbinding2.view.RxView; import com.jasonjan.headnews.R; import com.jasonjan.headnews.bean.news.MultiNewsArticleDataBean; import com.jasonjan.headnews.main.ErrorAction; import com.jasonjan.headnews.main.IntentAction; import com.jasonjan.headnews.util.ImageLoader; import com.jasonjan.headnews.util.SettingUtil; import com.jasonjan.headnews.util.TimeUtil; import com.jasonjan.headnews.widget.CircleImageView; import java.util.concurrent.TimeUnit; import io.reactivex.functions.Consumer; import me.drakeet.multitype.ItemViewBinder; /** * Created by JasonJan on 2017/12/12. */ public class NewsArticleTextViewBinder extends ItemViewBinder<MultiNewsArticleDataBean,NewsArticleTextViewBinder.ViewHolder>{ private static final String TAG = "NewsArticleTextViewBind"; @NonNull @Override protected NewsArticleTextViewBinder.ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { View view = inflater.inflate(R.layout.item_news_article_text, parent, false); return new ViewHolder(view); } @Override protected void onBindViewHolder(@NonNull final NewsArticleTextViewBinder.ViewHolder holder, @NonNull final MultiNewsArticleDataBean item) { final Context context = holder.itemView.getContext(); try { if (null != item.getUser_info()) { String avatar_url = item.getUser_info().getAvatar_url(); if (!TextUtils.isEmpty(avatar_url)) { ImageLoader.loadCenterCrop(context, avatar_url, holder.iv_media, R.color.viewBackground); } } String tv_title = item.getTitle(); String tv_abstract = item.getAbstractX(); String tv_source = item.getSource(); String tv_comment_count = item.getComment_count() + "评论"; String tv_datetime = item.getBehot_time() + ""; if (!TextUtils.isEmpty(tv_datetime)) { tv_datetime = TimeUtil.getTimeStampAgo(tv_datetime); } holder.tv_title.setText(tv_title); holder.tv_title.setTextSize(SettingUtil.getInstance().getTextSize()); holder.tv_abstract.setText(tv_abstract); holder.tv_extra.setText(tv_source + " - " + tv_comment_count + " - " + tv_datetime); holder.iv_dots.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { PopupMenu popupMenu = new PopupMenu(context, holder.iv_dots, Gravity.END, 0, R.style.MyPopupMenu); popupMenu.inflate(R.menu.menu_share); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menu) { int itemId = menu.getItemId(); if (itemId == R.id.action_share) { IntentAction.send(context, item.getTitle() + "\n" + item.getShare_url()); } return false; } }); popupMenu.show(); } }); RxView.clicks(holder.itemView) .throttleFirst(1, TimeUnit.SECONDS) .subscribe(new Consumer<Object>() { @Override public void accept(@io.reactivex.annotations.NonNull Object o) throws Exception { //NewsContentActivity.launch(item); } }); } catch (Exception e) { ErrorAction.print(e); } } class ViewHolder extends RecyclerView.ViewHolder { private CircleImageView iv_media; private TextView tv_extra; private TextView tv_title; private TextView tv_abstract; private ImageView iv_dots; ViewHolder(View itemView) { super(itemView); this.iv_media = itemView.findViewById(R.id.iv_media); this.tv_extra = itemView.findViewById(R.id.tv_extra); this.tv_title = itemView.findViewById(R.id.tv_title); this.tv_abstract = itemView.findViewById(R.id.tv_abstract); this.iv_dots = itemView.findViewById(R.id.iv_dots); } } }
6.效果预览
6.1.目前已经做好的东西
底部导航栏新闻主页面的所有类型。
包括3种主要的Fragment。
有段子页面(只有文字,下方有赞或者踩)
有普通页面(也有3中类型,文字或图片或视频三种绑定视图)
有问答页面(以问题开始,下方有多少个回答,右下方显示时间,中间显示3张图片或者纯文字)
以上就是新闻的所有页面。
6.2.效果预览
6.3.目前整个项目下载链接
链接:https://pan.baidu.com/s/1nvuvxB7 密码:2lle