TouTiao开源项目 分析笔记12 从总体到局部 构建视频主页面
1.构建视频主列表的整体碎片VideoTabLayout
1.1.首先创建一个VideoTabLayout
package com.jasonjan.headnews.module.video; import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import com.jasonjan.headnews.R;
import com.jasonjan.headnews.global.InitApp;
import com.jasonjan.headnews.adapter.BasePagerAdapter;
import com.jasonjan.headnews.test.Test_Fragment;
import com.jasonjan.headnews.util.SettingUtil; import java.util.ArrayList;
import java.util.List; /**
* Created by JasonJan on 2017/12/1.
*/ public class VideoTabLayout extends Fragment {
private static VideoTabLayout instance = null;
private static int pageSize = InitApp.AppContext.getResources().getStringArray(R.array.mobile_video_id).length;
private String categoryId[] = InitApp.AppContext.getResources().getStringArray(R.array.mobile_video_id);
private String categoryName[] = InitApp.AppContext.getResources().getStringArray(R.array.mobile_video_name);
private TabLayout tabLayout;
private ViewPager viewPager;
private List<Fragment> fragmentList = new ArrayList<>();
private BasePagerAdapter adapter; public static VideoTabLayout getInstance() {
if (instance == null) {
instance = new VideoTabLayout();
}
return instance;
} @Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_video_tab, container, false);
initView(view);
initData();
return view;
} @Override
public void onResume() {
super.onResume();
tabLayout.setBackgroundColor(SettingUtil.getInstance().getColor());
} private void initView(View view) {
tabLayout = view.findViewById(R.id.tab_layout_video);
viewPager = view.findViewById(R.id.view_pager_video); tabLayout.setupWithViewPager(viewPager);
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
tabLayout.setBackgroundColor(SettingUtil.getInstance().getColor());
viewPager.setOffscreenPageLimit(pageSize);
} private void initData() {
for (int i = 0; i < categoryId.length; i++) {
Fragment fragment = VideoArticleView.newInstance(categoryId[i]);
fragmentList.add(fragment);
}
adapter = new BasePagerAdapter(getChildFragmentManager(), fragmentList, categoryName);
viewPager.setAdapter(adapter);
} @Override
public void onDestroy() {
if (instance != null) {
instance = null;
}
super.onDestroy();
}
}
这里先声明视频中的小碎片名称为:VideoArticleView。
后面详细分析这个Fragment。主要就是视频的一些小分类。用的是同一种布局方式。
1.2.这个片段需要一个布局fragment_video_tab.xml
<?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"> <android.support.design.widget.TabLayout
android:id="@+id/tab_layout_video"
style="@style/TabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="@style/AppTheme.AppBarOverlay"
app:tabTextColor="@color/gray">
</android.support.design.widget.TabLayout> <android.support.v4.view.ViewPager
android:id="@+id/view_pager_video"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:layout="@layout/fragment_list">
</android.support.v4.view.ViewPager> </LinearLayout>
1.3.布局真实效果预览
1.4.然后就是上方tablayout中的静态文字
在资源文件中values中的mobile_video_category.xml
<?xml version="1.0" encoding="utf-8"?>
<resources> <string-array name="mobile_video_name">
<item>推荐</item>
<item>音乐</item>
<item>搞笑</item>
<item>社会</item>
<item>小品</item> <item>生活</item>
<item>影视</item>
<item>娱乐</item>
<item>呆萌</item>
<item>游戏</item> <item>原创</item>
<item>开眼</item> </string-array> <string-array name="mobile_video_id">
<item>video</item>
<item>subv_voice</item>
<item>subv_funny</item>
<item>subv_society</item>
<item>subv_comedy</item> <item>subv_life</item>
<item>subv_movie</item>
<item>subv_entertainment</item>
<item>subv_cute</item>
<item>subv_game</item> <item>subv_boutique</item>
<item>subv_broaden_view</item> </string-array> </resources>
1.5.然后就是将视频主列表的十二种类型用一个BasePagerAdapter联系起来
下面的代码在上方的VideoTabLayout.java中的一个函数中,这里再重复拿出来讲一下。
private void initData() {
for (int i = 0; i < categoryId.length; i++) {
Fragment fragment = VideoArticleView.newInstance(categoryId[i]);
fragmentList.add(fragment);
}
adapter = new BasePagerAdapter(getChildFragmentManager(), fragmentList, categoryName);
viewPager.setAdapter(adapter);
}
1.6.看一下集合所有分类的碎片的适配器==>BasePagerAdapter
public class BasePagerAdapter extends FragmentStatePagerAdapter { private List<Fragment> fragmentList;
private List<String> titleList; public BasePagerAdapter(FragmentManager fm, List<Fragment> fragmentList, String[] titles) {
super(fm);
this.fragmentList = fragmentList;
this.titleList = new ArrayList<>(Arrays.asList(titles));
} public BasePagerAdapter(FragmentManager fm, List<Fragment> fragmentList, List<String> titleList) {
super(fm);
this.fragmentList = fragmentList;
this.titleList = titleList;
} @Override
public Fragment getItem(int position) {
return fragmentList.get(position);
} @Override
public int getCount() {
return titleList.size();
} @Override
public CharSequence getPageTitle(int position) {
return titleList.get(position);
} @Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
} public void recreateItems(List<Fragment> fragmentList, List<String> titleList) {
this.fragmentList = fragmentList;
this.titleList = titleList;
notifyDataSetChanged();
}
}
1.7.第一阶段结束,主要完成了VideoTabLayout这个视频主页面和相应的逻辑。
第二阶段主要处理12个分片段的布局和逻辑了。
2.视频系列的文章的基础Bean类
2.1.第一集团数据返回==>调用API后返回的数据(包括很多杂项)
/**
* data : {"status":10,"user_id":"toutiao","video_id":"f2aeddda2a894e53bb3f2cf98994aadb","big_thumbs":[{"img_num":16,"img_url":"https://p1.pstatp.com/origin/19cc000499f3a6986d59","img_x_size":160,"img_y_size":90,"img_x_len":1,"img_y_len":16}],"video_duration":84.8,"video_list":{"video_1":{"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNWE2YzA4ZmJjZWQxZmIzY2ZhMDdkZGE3Zjg0ZTNkZDUvNThkZGJlMjAvdmlkZW8vbS8xMTQ0YzNiMDAwMDBjMWU1MWIwMWQ1ZjIyMGE0MzMyMTUyNGQwOTQ0MjU5MDI5NmU1NDI3Yjc5NGNlLw==","bitrate":369405,"definition":"360p","main_url":"aHR0cDovL3Y2LjM2NXlnLmNvbS92aWRlby9tLzExNDRjM2IwMDAwMGMxZTUxYjAxZDVmMjIwYTQzMzIxNTI0ZDA5NDQyNTkwMjk2ZTU0MjdiNzk0Y2UvP0V4cGlyZXM9MTQ5MDkzMDczNiZBV1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNb1Myb1BqN2FLWCZTaWduYXR1cmU9WWNmakZDNnMxSHFhQ0NxeVZMd3ZkRWNlcXg0JTNE","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":4630326,"socket_buffer":221643000,"user_video_proxy":1,"vheight":360,"vtype":"mp4","vwidth":640},"video_2":{"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNTk0ZTZjNDZjMjliZDkxY2EwZWJhMTFkM2RlMGIxN2EvNThkZGJlMjAvdmlkZW8vbS8yMjBlNmU2MjY3Mjg4NDU0YzkwOTFjOGYyMTZlZThiOWEwMjExNDRiZjAwMDAwMDZmNTE3YjkxMTk1Lw==","bitrate":577524,"definition":"480p","main_url":"aHR0cDovL3Y2LjM2NXlnLmNvbS92aWRlby9tLzIyMGU2ZTYyNjcyODg0NTRjOTA5MWM4ZjIxNmVlOGI5YTAyMTE0NGJmMDAwMDAwNmY1MTdiOTExOTUvP0V4cGlyZXM9MTQ5MDkzMDczNiZBV1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNb1Myb1BqN2FLWCZTaWduYXR1cmU9JTJGbEtPMld4QVVtcUtqUGo4TWw5cFpxaFNSeEklM0Q=","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":6836189,"socket_buffer":346514400,"user_video_proxy":1,"vheight":480,"vtype":"mp4","vwidth":854},"video_3":{"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNzM4NTJiOTYxNDgyMzc0MDY2NWIyN2VkODZhNWVhMTEvNThkZGJlMjAvdmlkZW8vbS8yMjA0NTViMDUyMjFjYTg0MDAxOWFjZjkwZDNmZGFmZTNhZDExNDQ4ZGMwMDAwMjRkOTFkNmZkNzZhLw==","bitrate":1274484,"definition":"720p","main_url":"aHR0cDovL3YzLjM2NXlnLmNvbS83Mzg1MmI5NjE0ODIzNzQwNjY1YjI3ZWQ4NmE1ZWExMS81OGRkYmUyMC92aWRlby9tLzIyMDQ1NWIwNTIyMWNhODQwMDE5YWNmOTBkM2ZkYWZlM2FkMTE0NDhkYzAwMDAyNGQ5MWQ2ZmQ3NmEv","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":14223659,"socket_buffer":764690400,"user_video_proxy":1,"vheight":720,"vtype":"mp4","vwidth":1280}}}
* message : success
* code : 0
* total : 3
*/
2.2.第二集团数据返回==>处理上方的data中的数据
/**
* status : 10
* user_id : toutiao
* video_id : f2aeddda2a894e53bb3f2cf98994aadb
* big_thumbs : [{"img_num":16,"img_url":"https://p1.pstatp.com/origin/19cc000499f3a6986d59","img_x_size":160,"img_y_size":90,"img_x_len":1,"img_y_len":16}]
* video_duration : 84.8
* video_list : {"video_1":{"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNWE2YzA4ZmJjZWQxZmIzY2ZhMDdkZGE3Zjg0ZTNkZDUvNThkZGJlMjAvdmlkZW8vbS8xMTQ0YzNiMDAwMDBjMWU1MWIwMWQ1ZjIyMGE0MzMyMTUyNGQwOTQ0MjU5MDI5NmU1NDI3Yjc5NGNlLw==","bitrate":369405,"definition":"360p","main_url":"aHR0cDovL3Y2LjM2NXlnLmNvbS92aWRlby9tLzExNDRjM2IwMDAwMGMxZTUxYjAxZDVmMjIwYTQzMzIxNTI0ZDA5NDQyNTkwMjk2ZTU0MjdiNzk0Y2UvP0V4cGlyZXM9MTQ5MDkzMDczNiZBV1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNb1Myb1BqN2FLWCZTaWduYXR1cmU9WWNmakZDNnMxSHFhQ0NxeVZMd3ZkRWNlcXg0JTNE","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":4630326,"socket_buffer":221643000,"user_video_proxy":1,"vheight":360,"vtype":"mp4","vwidth":640},"video_2":{"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNTk0ZTZjNDZjMjliZDkxY2EwZWJhMTFkM2RlMGIxN2EvNThkZGJlMjAvdmlkZW8vbS8yMjBlNmU2MjY3Mjg4NDU0YzkwOTFjOGYyMTZlZThiOWEwMjExNDRiZjAwMDAwMDZmNTE3YjkxMTk1Lw==","bitrate":577524,"definition":"480p","main_url":"aHR0cDovL3Y2LjM2NXlnLmNvbS92aWRlby9tLzIyMGU2ZTYyNjcyODg0NTRjOTA5MWM4ZjIxNmVlOGI5YTAyMTE0NGJmMDAwMDAwNmY1MTdiOTExOTUvP0V4cGlyZXM9MTQ5MDkzMDczNiZBV1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNb1Myb1BqN2FLWCZTaWduYXR1cmU9JTJGbEtPMld4QVVtcUtqUGo4TWw5cFpxaFNSeEklM0Q=","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":6836189,"socket_buffer":346514400,"user_video_proxy":1,"vheight":480,"vtype":"mp4","vwidth":854},"video_3":{"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNzM4NTJiOTYxNDgyMzc0MDY2NWIyN2VkODZhNWVhMTEvNThkZGJlMjAvdmlkZW8vbS8yMjA0NTViMDUyMjFjYTg0MDAxOWFjZjkwZDNmZGFmZTNhZDExNDQ4ZGMwMDAwMjRkOTFkNmZkNzZhLw==","bitrate":1274484,"definition":"720p","main_url":"aHR0cDovL3YzLjM2NXlnLmNvbS83Mzg1MmI5NjE0ODIzNzQwNjY1YjI3ZWQ4NmE1ZWExMS81OGRkYmUyMC92aWRlby9tLzIyMDQ1NWIwNTIyMWNhODQwMDE5YWNmOTBkM2ZkYWZlM2FkMTE0NDhkYzAwMDAyNGQ5MWQ2ZmQ3NmEv","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":14223659,"socket_buffer":764690400,"user_video_proxy":1,"vheight":720,"vtype":"mp4","vwidth":1280}}
*/
2.3.整个VideoContentBean类
package com.jasonjan.headnews.bean.video; import java.util.List; /**
* Created by JasonJan on 2017/12/14.
*/ public class VideoContentBean { /**
* data : {"status":10,"user_id":"toutiao","video_id":"f2aeddda2a894e53bb3f2cf98994aadb","big_thumbs":[{"img_num":16,"img_url":"https://p1.pstatp.com/origin/19cc000499f3a6986d59","img_x_size":160,"img_y_size":90,"img_x_len":1,"img_y_len":16}],"video_duration":84.8,"video_list":{"video_1":{"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNWE2YzA4ZmJjZWQxZmIzY2ZhMDdkZGE3Zjg0ZTNkZDUvNThkZGJlMjAvdmlkZW8vbS8xMTQ0YzNiMDAwMDBjMWU1MWIwMWQ1ZjIyMGE0MzMyMTUyNGQwOTQ0MjU5MDI5NmU1NDI3Yjc5NGNlLw==","bitrate":369405,"definition":"360p","main_url":"aHR0cDovL3Y2LjM2NXlnLmNvbS92aWRlby9tLzExNDRjM2IwMDAwMGMxZTUxYjAxZDVmMjIwYTQzMzIxNTI0ZDA5NDQyNTkwMjk2ZTU0MjdiNzk0Y2UvP0V4cGlyZXM9MTQ5MDkzMDczNiZBV1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNb1Myb1BqN2FLWCZTaWduYXR1cmU9WWNmakZDNnMxSHFhQ0NxeVZMd3ZkRWNlcXg0JTNE","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":4630326,"socket_buffer":221643000,"user_video_proxy":1,"vheight":360,"vtype":"mp4","vwidth":640},"video_2":{"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNTk0ZTZjNDZjMjliZDkxY2EwZWJhMTFkM2RlMGIxN2EvNThkZGJlMjAvdmlkZW8vbS8yMjBlNmU2MjY3Mjg4NDU0YzkwOTFjOGYyMTZlZThiOWEwMjExNDRiZjAwMDAwMDZmNTE3YjkxMTk1Lw==","bitrate":577524,"definition":"480p","main_url":"aHR0cDovL3Y2LjM2NXlnLmNvbS92aWRlby9tLzIyMGU2ZTYyNjcyODg0NTRjOTA5MWM4ZjIxNmVlOGI5YTAyMTE0NGJmMDAwMDAwNmY1MTdiOTExOTUvP0V4cGlyZXM9MTQ5MDkzMDczNiZBV1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNb1Myb1BqN2FLWCZTaWduYXR1cmU9JTJGbEtPMld4QVVtcUtqUGo4TWw5cFpxaFNSeEklM0Q=","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":6836189,"socket_buffer":346514400,"user_video_proxy":1,"vheight":480,"vtype":"mp4","vwidth":854},"video_3":{"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNzM4NTJiOTYxNDgyMzc0MDY2NWIyN2VkODZhNWVhMTEvNThkZGJlMjAvdmlkZW8vbS8yMjA0NTViMDUyMjFjYTg0MDAxOWFjZjkwZDNmZGFmZTNhZDExNDQ4ZGMwMDAwMjRkOTFkNmZkNzZhLw==","bitrate":1274484,"definition":"720p","main_url":"aHR0cDovL3YzLjM2NXlnLmNvbS83Mzg1MmI5NjE0ODIzNzQwNjY1YjI3ZWQ4NmE1ZWExMS81OGRkYmUyMC92aWRlby9tLzIyMDQ1NWIwNTIyMWNhODQwMDE5YWNmOTBkM2ZkYWZlM2FkMTE0NDhkYzAwMDAyNGQ5MWQ2ZmQ3NmEv","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":14223659,"socket_buffer":764690400,"user_video_proxy":1,"vheight":720,"vtype":"mp4","vwidth":1280}}}
* message : success
* code : 0
* total : 3
*/ private DataBean data;
private String message;
private int code;
private int total; public DataBean getData() {
return data;
} public void setData(DataBean data) {
this.data = data;
} public String getMessage() {
return message;
} public void setMessage(String message) {
this.message = message;
} public int getCode() {
return code;
} public void setCode(int code) {
this.code = code;
} public int getTotal() {
return total;
} public void setTotal(int total) {
this.total = total;
} public static class DataBean {
/**
* status : 10
* user_id : toutiao
* video_id : f2aeddda2a894e53bb3f2cf98994aadb
* big_thumbs : [{"img_num":16,"img_url":"https://p1.pstatp.com/origin/19cc000499f3a6986d59","img_x_size":160,"img_y_size":90,"img_x_len":1,"img_y_len":16}]
* video_duration : 84.8
* video_list : {"video_1":{"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNWE2YzA4ZmJjZWQxZmIzY2ZhMDdkZGE3Zjg0ZTNkZDUvNThkZGJlMjAvdmlkZW8vbS8xMTQ0YzNiMDAwMDBjMWU1MWIwMWQ1ZjIyMGE0MzMyMTUyNGQwOTQ0MjU5MDI5NmU1NDI3Yjc5NGNlLw==","bitrate":369405,"definition":"360p","main_url":"aHR0cDovL3Y2LjM2NXlnLmNvbS92aWRlby9tLzExNDRjM2IwMDAwMGMxZTUxYjAxZDVmMjIwYTQzMzIxNTI0ZDA5NDQyNTkwMjk2ZTU0MjdiNzk0Y2UvP0V4cGlyZXM9MTQ5MDkzMDczNiZBV1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNb1Myb1BqN2FLWCZTaWduYXR1cmU9WWNmakZDNnMxSHFhQ0NxeVZMd3ZkRWNlcXg0JTNE","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":4630326,"socket_buffer":221643000,"user_video_proxy":1,"vheight":360,"vtype":"mp4","vwidth":640},"video_2":{"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNTk0ZTZjNDZjMjliZDkxY2EwZWJhMTFkM2RlMGIxN2EvNThkZGJlMjAvdmlkZW8vbS8yMjBlNmU2MjY3Mjg4NDU0YzkwOTFjOGYyMTZlZThiOWEwMjExNDRiZjAwMDAwMDZmNTE3YjkxMTk1Lw==","bitrate":577524,"definition":"480p","main_url":"aHR0cDovL3Y2LjM2NXlnLmNvbS92aWRlby9tLzIyMGU2ZTYyNjcyODg0NTRjOTA5MWM4ZjIxNmVlOGI5YTAyMTE0NGJmMDAwMDAwNmY1MTdiOTExOTUvP0V4cGlyZXM9MTQ5MDkzMDczNiZBV1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNb1Myb1BqN2FLWCZTaWduYXR1cmU9JTJGbEtPMld4QVVtcUtqUGo4TWw5cFpxaFNSeEklM0Q=","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":6836189,"socket_buffer":346514400,"user_video_proxy":1,"vheight":480,"vtype":"mp4","vwidth":854},"video_3":{"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNzM4NTJiOTYxNDgyMzc0MDY2NWIyN2VkODZhNWVhMTEvNThkZGJlMjAvdmlkZW8vbS8yMjA0NTViMDUyMjFjYTg0MDAxOWFjZjkwZDNmZGFmZTNhZDExNDQ4ZGMwMDAwMjRkOTFkNmZkNzZhLw==","bitrate":1274484,"definition":"720p","main_url":"aHR0cDovL3YzLjM2NXlnLmNvbS83Mzg1MmI5NjE0ODIzNzQwNjY1YjI3ZWQ4NmE1ZWExMS81OGRkYmUyMC92aWRlby9tLzIyMDQ1NWIwNTIyMWNhODQwMDE5YWNmOTBkM2ZkYWZlM2FkMTE0NDhkYzAwMDAyNGQ5MWQ2ZmQ3NmEv","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":14223659,"socket_buffer":764690400,"user_video_proxy":1,"vheight":720,"vtype":"mp4","vwidth":1280}}
*/ private int status;
private String user_id;
private String video_id;
private double video_duration;
private VideoListBean video_list;
private List<BigThumbsBean> big_thumbs; public int getStatus() {
return status;
} public void setStatus(int status) {
this.status = status;
} public String getUser_id() {
return user_id;
} public void setUser_id(String user_id) {
this.user_id = user_id;
} public String getVideo_id() {
return video_id;
} public void setVideo_id(String video_id) {
this.video_id = video_id;
} public double getVideo_duration() {
return video_duration;
} public void setVideo_duration(double video_duration) {
this.video_duration = video_duration;
} public VideoListBean getVideo_list() {
return video_list;
} public void setVideo_list(VideoListBean video_list) {
this.video_list = video_list;
} public List<BigThumbsBean> getBig_thumbs() {
return big_thumbs;
} public void setBig_thumbs(List<BigThumbsBean> big_thumbs) {
this.big_thumbs = big_thumbs;
} public static class VideoListBean {
/**
* video_1 : {"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNWE2YzA4ZmJjZWQxZmIzY2ZhMDdkZGE3Zjg0ZTNkZDUvNThkZGJlMjAvdmlkZW8vbS8xMTQ0YzNiMDAwMDBjMWU1MWIwMWQ1ZjIyMGE0MzMyMTUyNGQwOTQ0MjU5MDI5NmU1NDI3Yjc5NGNlLw==","bitrate":369405,"definition":"360p","main_url":"aHR0cDovL3Y2LjM2NXlnLmNvbS92aWRlby9tLzExNDRjM2IwMDAwMGMxZTUxYjAxZDVmMjIwYTQzMzIxNTI0ZDA5NDQyNTkwMjk2ZTU0MjdiNzk0Y2UvP0V4cGlyZXM9MTQ5MDkzMDczNiZBV1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNb1Myb1BqN2FLWCZTaWduYXR1cmU9WWNmakZDNnMxSHFhQ0NxeVZMd3ZkRWNlcXg0JTNE","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":4630326,"socket_buffer":221643000,"user_video_proxy":1,"vheight":360,"vtype":"mp4","vwidth":640}
* video_2 : {"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNTk0ZTZjNDZjMjliZDkxY2EwZWJhMTFkM2RlMGIxN2EvNThkZGJlMjAvdmlkZW8vbS8yMjBlNmU2MjY3Mjg4NDU0YzkwOTFjOGYyMTZlZThiOWEwMjExNDRiZjAwMDAwMDZmNTE3YjkxMTk1Lw==","bitrate":577524,"definition":"480p","main_url":"aHR0cDovL3Y2LjM2NXlnLmNvbS92aWRlby9tLzIyMGU2ZTYyNjcyODg0NTRjOTA5MWM4ZjIxNmVlOGI5YTAyMTE0NGJmMDAwMDAwNmY1MTdiOTExOTUvP0V4cGlyZXM9MTQ5MDkzMDczNiZBV1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNb1Myb1BqN2FLWCZTaWduYXR1cmU9JTJGbEtPMld4QVVtcUtqUGo4TWw5cFpxaFNSeEklM0Q=","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":6836189,"socket_buffer":346514400,"user_video_proxy":1,"vheight":480,"vtype":"mp4","vwidth":854}
* video_3 : {"backup_url_1":"aHR0cDovL3Y3LnBzdGF0cC5jb20vNzM4NTJiOTYxNDgyMzc0MDY2NWIyN2VkODZhNWVhMTEvNThkZGJlMjAvdmlkZW8vbS8yMjA0NTViMDUyMjFjYTg0MDAxOWFjZjkwZDNmZGFmZTNhZDExNDQ4ZGMwMDAwMjRkOTFkNmZkNzZhLw==","bitrate":1274484,"definition":"720p","main_url":"aHR0cDovL3YzLjM2NXlnLmNvbS83Mzg1MmI5NjE0ODIzNzQwNjY1YjI3ZWQ4NmE1ZWExMS81OGRkYmUyMC92aWRlby9tLzIyMDQ1NWIwNTIyMWNhODQwMDE5YWNmOTBkM2ZkYWZlM2FkMTE0NDhkYzAwMDAyNGQ5MWQ2ZmQ3NmEv","preload_interval":25,"preload_max_step":10,"preload_min_step":5,"preload_size":327680,"size":14223659,"socket_buffer":764690400,"user_video_proxy":1,"vheight":720,"vtype":"mp4","vwidth":1280}
*/ private Video1Bean video_1;
private Video2Bean video_2;
private Video3Bean video_3; public Video1Bean getVideo_1() {
return video_1;
} public void setVideo_1(Video1Bean video_1) {
this.video_1 = video_1;
} public Video2Bean getVideo_2() {
return video_2;
} public void setVideo_2(Video2Bean video_2) {
this.video_2 = video_2;
} public Video3Bean getVideo_3() {
return video_3;
} public void setVideo_3(Video3Bean video_3) {
this.video_3 = video_3;
} public static class Video1Bean {
/**
* backup_url_1 : aHR0cDovL3Y3LnBzdGF0cC5jb20vNWE2YzA4ZmJjZWQxZmIzY2ZhMDdkZGE3Zjg0ZTNkZDUvNThkZGJlMjAvdmlkZW8vbS8xMTQ0YzNiMDAwMDBjMWU1MWIwMWQ1ZjIyMGE0MzMyMTUyNGQwOTQ0MjU5MDI5NmU1NDI3Yjc5NGNlLw==
* bitrate : 369405
* definition : 360p
* main_url : aHR0cDovL3Y2LjM2NXlnLmNvbS92aWRlby9tLzExNDRjM2IwMDAwMGMxZTUxYjAxZDVmMjIwYTQzMzIxNTI0ZDA5NDQyNTkwMjk2ZTU0MjdiNzk0Y2UvP0V4cGlyZXM9MTQ5MDkzMDczNiZBV1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNb1Myb1BqN2FLWCZTaWduYXR1cmU9WWNmakZDNnMxSHFhQ0NxeVZMd3ZkRWNlcXg0JTNE
* preload_interval : 25
* preload_max_step : 10
* preload_min_step : 5
* preload_size : 327680
* size : 4630326
* socket_buffer : 221643000
* user_video_proxy : 1
* vheight : 360
* vtype : mp4
* vwidth : 640
*/ private String backup_url_1;
private int bitrate;
private String definition;
private String main_url;
private int preload_interval;
private int preload_max_step;
private int preload_min_step;
private int preload_size;
private int size;
private int socket_buffer;
private int user_video_proxy;
private int vheight;
private String vtype;
private int vwidth; public String getBackup_url_1() {
return backup_url_1;
} public void setBackup_url_1(String backup_url_1) {
this.backup_url_1 = backup_url_1;
} public int getBitrate() {
return bitrate;
} public void setBitrate(int bitrate) {
this.bitrate = bitrate;
} public String getDefinition() {
return definition;
} public void setDefinition(String definition) {
this.definition = definition;
} public String getMain_url() {
return main_url;
} public void setMain_url(String main_url) {
this.main_url = main_url;
} public int getPreload_interval() {
return preload_interval;
} public void setPreload_interval(int preload_interval) {
this.preload_interval = preload_interval;
} public int getPreload_max_step() {
return preload_max_step;
} public void setPreload_max_step(int preload_max_step) {
this.preload_max_step = preload_max_step;
} public int getPreload_min_step() {
return preload_min_step;
} public void setPreload_min_step(int preload_min_step) {
this.preload_min_step = preload_min_step;
} public int getPreload_size() {
return preload_size;
} public void setPreload_size(int preload_size) {
this.preload_size = preload_size;
} public int getSize() {
return size;
} public void setSize(int size) {
this.size = size;
} public int getSocket_buffer() {
return socket_buffer;
} public void setSocket_buffer(int socket_buffer) {
this.socket_buffer = socket_buffer;
} public int getUser_video_proxy() {
return user_video_proxy;
} public void setUser_video_proxy(int user_video_proxy) {
this.user_video_proxy = user_video_proxy;
} public int getVheight() {
return vheight;
} public void setVheight(int vheight) {
this.vheight = vheight;
} public String getVtype() {
return vtype;
} public void setVtype(String vtype) {
this.vtype = vtype;
} public int getVwidth() {
return vwidth;
} public void setVwidth(int vwidth) {
this.vwidth = vwidth;
}
} public static class Video2Bean {
/**
* backup_url_1 : aHR0cDovL3Y3LnBzdGF0cC5jb20vNTk0ZTZjNDZjMjliZDkxY2EwZWJhMTFkM2RlMGIxN2EvNThkZGJlMjAvdmlkZW8vbS8yMjBlNmU2MjY3Mjg4NDU0YzkwOTFjOGYyMTZlZThiOWEwMjExNDRiZjAwMDAwMDZmNTE3YjkxMTk1Lw==
* bitrate : 577524
* definition : 480p
* main_url : aHR0cDovL3Y2LjM2NXlnLmNvbS92aWRlby9tLzIyMGU2ZTYyNjcyODg0NTRjOTA5MWM4ZjIxNmVlOGI5YTAyMTE0NGJmMDAwMDAwNmY1MTdiOTExOTUvP0V4cGlyZXM9MTQ5MDkzMDczNiZBV1NBY2Nlc3NLZXlJZD1xaDBoOVRkY0VNb1Myb1BqN2FLWCZTaWduYXR1cmU9JTJGbEtPMld4QVVtcUtqUGo4TWw5cFpxaFNSeEklM0Q=
* preload_interval : 25
* preload_max_step : 10
* preload_min_step : 5
* preload_size : 327680
* size : 6836189
* socket_buffer : 346514400
* user_video_proxy : 1
* vheight : 480
* vtype : mp4
* vwidth : 854
*/ private String backup_url_1;
private int bitrate;
private String definition;
private String main_url;
private int preload_interval;
private int preload_max_step;
private int preload_min_step;
private int preload_size;
private int size;
private int socket_buffer;
private int user_video_proxy;
private int vheight;
private String vtype;
private int vwidth; public String getBackup_url_1() {
return backup_url_1;
} public void setBackup_url_1(String backup_url_1) {
this.backup_url_1 = backup_url_1;
} public int getBitrate() {
return bitrate;
} public void setBitrate(int bitrate) {
this.bitrate = bitrate;
} public String getDefinition() {
return definition;
} public void setDefinition(String definition) {
this.definition = definition;
} public String getMain_url() {
return main_url;
} public void setMain_url(String main_url) {
this.main_url = main_url;
} public int getPreload_interval() {
return preload_interval;
} public void setPreload_interval(int preload_interval) {
this.preload_interval = preload_interval;
} public int getPreload_max_step() {
return preload_max_step;
} public void setPreload_max_step(int preload_max_step) {
this.preload_max_step = preload_max_step;
} public int getPreload_min_step() {
return preload_min_step;
} public void setPreload_min_step(int preload_min_step) {
this.preload_min_step = preload_min_step;
} public int getPreload_size() {
return preload_size;
} public void setPreload_size(int preload_size) {
this.preload_size = preload_size;
} public int getSize() {
return size;
} public void setSize(int size) {
this.size = size;
} public int getSocket_buffer() {
return socket_buffer;
} public void setSocket_buffer(int socket_buffer) {
this.socket_buffer = socket_buffer;
} public int getUser_video_proxy() {
return user_video_proxy;
} public void setUser_video_proxy(int user_video_proxy) {
this.user_video_proxy = user_video_proxy;
} public int getVheight() {
return vheight;
} public void setVheight(int vheight) {
this.vheight = vheight;
} public String getVtype() {
return vtype;
} public void setVtype(String vtype) {
this.vtype = vtype;
} public int getVwidth() {
return vwidth;
} public void setVwidth(int vwidth) {
this.vwidth = vwidth;
}
} public static class Video3Bean {
/**
* backup_url_1 : aHR0cDovL3Y3LnBzdGF0cC5jb20vNzM4NTJiOTYxNDgyMzc0MDY2NWIyN2VkODZhNWVhMTEvNThkZGJlMjAvdmlkZW8vbS8yMjA0NTViMDUyMjFjYTg0MDAxOWFjZjkwZDNmZGFmZTNhZDExNDQ4ZGMwMDAwMjRkOTFkNmZkNzZhLw==
* bitrate : 1274484
* definition : 720p
* main_url : aHR0cDovL3YzLjM2NXlnLmNvbS83Mzg1MmI5NjE0ODIzNzQwNjY1YjI3ZWQ4NmE1ZWExMS81OGRkYmUyMC92aWRlby9tLzIyMDQ1NWIwNTIyMWNhODQwMDE5YWNmOTBkM2ZkYWZlM2FkMTE0NDhkYzAwMDAyNGQ5MWQ2ZmQ3NmEv
* preload_interval : 25
* preload_max_step : 10
* preload_min_step : 5
* preload_size : 327680
* size : 14223659
* socket_buffer : 764690400
* user_video_proxy : 1
* vheight : 720
* vtype : mp4
* vwidth : 1280
*/ private String backup_url_1;
private int bitrate;
private String definition;
private String main_url;
private int preload_interval;
private int preload_max_step;
private int preload_min_step;
private int preload_size;
private int size;
private int socket_buffer;
private int user_video_proxy;
private int vheight;
private String vtype;
private int vwidth; public String getBackup_url_1() {
return backup_url_1;
} public void setBackup_url_1(String backup_url_1) {
this.backup_url_1 = backup_url_1;
} public int getBitrate() {
return bitrate;
} public void setBitrate(int bitrate) {
this.bitrate = bitrate;
} public String getDefinition() {
return definition;
} public void setDefinition(String definition) {
this.definition = definition;
} public String getMain_url() {
return main_url;
} public void setMain_url(String main_url) {
this.main_url = main_url;
} public int getPreload_interval() {
return preload_interval;
} public void setPreload_interval(int preload_interval) {
this.preload_interval = preload_interval;
} public int getPreload_max_step() {
return preload_max_step;
} public void setPreload_max_step(int preload_max_step) {
this.preload_max_step = preload_max_step;
} public int getPreload_min_step() {
return preload_min_step;
} public void setPreload_min_step(int preload_min_step) {
this.preload_min_step = preload_min_step;
} public int getPreload_size() {
return preload_size;
} public void setPreload_size(int preload_size) {
this.preload_size = preload_size;
} public int getSize() {
return size;
} public void setSize(int size) {
this.size = size;
} public int getSocket_buffer() {
return socket_buffer;
} public void setSocket_buffer(int socket_buffer) {
this.socket_buffer = socket_buffer;
} public int getUser_video_proxy() {
return user_video_proxy;
} public void setUser_video_proxy(int user_video_proxy) {
this.user_video_proxy = user_video_proxy;
} public int getVheight() {
return vheight;
} public void setVheight(int vheight) {
this.vheight = vheight;
} public String getVtype() {
return vtype;
} public void setVtype(String vtype) {
this.vtype = vtype;
} public int getVwidth() {
return vwidth;
} public void setVwidth(int vwidth) {
this.vwidth = vwidth;
}
}
} public static class BigThumbsBean {
/**
* img_num : 16
* img_url : https://p1.pstatp.com/origin/19cc000499f3a6986d59
* img_x_size : 160
* img_y_size : 90
* img_x_len : 1
* img_y_len : 16
*/ private int img_num;
private String img_url;
private int img_x_size;
private int img_y_size;
private int img_x_len;
private int img_y_len; public int getImg_num() {
return img_num;
} public void setImg_num(int img_num) {
this.img_num = img_num;
} public String getImg_url() {
return img_url;
} public void setImg_url(String img_url) {
this.img_url = img_url;
} public int getImg_x_size() {
return img_x_size;
} public void setImg_x_size(int img_x_size) {
this.img_x_size = img_x_size;
} public int getImg_y_size() {
return img_y_size;
} public void setImg_y_size(int img_y_size) {
this.img_y_size = img_y_size;
} public int getImg_x_len() {
return img_x_len;
} public void setImg_x_len(int img_x_len) {
this.img_x_len = img_x_len;
} public int getImg_y_len() {
return img_y_len;
} public void setImg_y_len(int img_y_len) {
this.img_y_len = img_y_len;
}
}
}
}
这个类比较庞大,都是按照服务器返回的数据而对应建立的。
3.视频系列的视图以及处理器控制
3.1.最底层视图以及处理器接口
public interface IVideoArticle { interface View extends IBaseListView<Presenter> { /**
* 请求数据
*/
void onLoadData();
} interface Presenter extends IBasePresenter { /**
* 请求数据
*/
void doLoadData(String... category); /**
* 再起请求数据
*/
void doLoadMoreData(); /**
* 设置适配器
*/
void doSetAdapter(List<MultiNewsArticleDataBean> dataBeen);
}
}
3.2.视频系列的视图
package com.jasonjan.headnews.module.video; 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/14.
*/ public class VideoArticleView extends BaseListFragment<IVideoArticle.Presenter> implements IVideoArticle.View {
private static final String TAG="VideoArticleView";
private String categoryId; public static VideoArticleView newInstance(String categoryId){
Bundle bundle=new Bundle();
bundle.putString(TAG,categoryId);
VideoArticleView videoArticleView=new VideoArticleView();
videoArticleView.setArguments(bundle);
return videoArticleView;
} @Override
protected void initData() {
categoryId = getArguments().getString(TAG);
} @Override
protected void initView(View view){
super.initView(view);
super.initView(view);
adapter = new MultiTypeAdapter(oldItems);
Register.registerVideoArticleItem(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;
} /**
* API 跟新闻的一样 所以采用类似新闻的 presenter
*
* @param presenter
*/
@Override
public void setPresenter(IVideoArticle.Presenter presenter) {
if (null == presenter) {
this.presenter = new VideoArticlePresenter(this);
}
}
}
然后发现处理器还没有设置呢。
然后还有视图绑定也未实现(在自定义的Register中实现)
然后还有处理新老数据来刷新(在自定义的Diffback中实现)
3.3.视频系列的处理器
这个处理器可以就用新闻页面通用的一个处理器
不过我还是自己另外写了一个处理器
和新闻页面的处理器非常相似。
package com.jasonjan.headnews.module.video; import android.text.TextUtils; import com.google.gson.Gson;
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 io.reactivex.Observable;
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/14.
*/ public class VideoArticlePresenter implements IVideoArticle.Presenter{
private static final String TAG = "VideoArticlePresenter";
private IVideoArticle.View view;
private String category;
private String time;
private Gson gson = new Gson();
private List<MultiNewsArticleDataBean> dataList = new ArrayList<>(); VideoArticlePresenter(IVideoArticle.View view) {
this.view = view;
this.time = TimeUtil.getCurrentTimeStamp();
} @Override
public void doLoadData(String... category){
try {
if (null == this.category) {
this.category = category[0];
}
} catch (Exception e) {
ErrorAction.print(e);
} // 释放内存
if (dataList.size() > 100) {
dataList.clear();
} RetrofitFactory.getRetrofit().create(IMobileVideoApi.class)
.getVideoArticle(this.category, time)
.subscribeOn(Schedulers.io())
.observeOn(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;
}
} catch (NullPointerException e) {
ErrorAction.print(e);
}
// 过滤重复新闻(与上次刷新的数据比较)
for (MultiNewsArticleDataBean bean : dataList) {
if (bean.getTitle().equals(dataBean.getTitle())) {
return false;
}
}
return true;
}
})
.toList()
.compose(view.<List<MultiNewsArticleDataBean>>bindToLife())
.subscribe(new Consumer<List<MultiNewsArticleDataBean>>() {
@Override
public void accept(@NonNull List<MultiNewsArticleDataBean> list) throws Exception {
doSetAdapter(list);
}
}, 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> dataBeen) {
dataList.addAll(dataBeen);
view.onSetAdapter(dataList);
view.onHideLoading();
} @Override
public void doRefresh() {
if (dataList.size() != 0) {
dataList.clear();
time = TimeUtil.getCurrentTimeStamp();
}
doLoadData();
} @Override
public void doShowNetError() {
view.onHideLoading();
view.onShowNetError();
} }
3.4.视频系列文章的API请求
public interface IMobileVideoApi { /**
* 获取视频标题等信息
* http://is.snssdk.com/api/news/feed/v53/?category=subv_cute&refer=1&count=20&max_behot_time=1499321562&iid=11776029171&device_id=36394312781
*/
@GET("http://is.snssdk.com/api/news/feed/v62/?iid=5034850950&device_id=6096495334&refer=1&count=20&aid=13")
Observable<MultiNewsArticleBean> getVideoArticle(
@Query("category") String category,
@Query("max_behot_time") String maxBehotTime); /**
* 获取视频信息
* Api 生成较复杂 详情查看
* http://ib.365yg.com/video/urls/v/1/toutiao/mp4/视频ID?r=17位随机数&s=加密结果
*/
@GET
Observable<VideoContentBean> getVideoContent(@Url String url);
}
可以看到,请求视频的地址和请求之前新闻的网址是一样的
而且返回数据也一样==>Observable<MultiNewsArticleBean>
当然唯一不同的应该就是这个category,
如果带了这个参数,我猜想应该返回的东西都有带有视频的图片。
3.5.然后在Register类中注入数据类型
/**
* 注入视频类型
* @param adapter
*/
public static void registerVideoArticleItem(@NonNull MultiTypeAdapter adapter) {
adapter.register(MultiNewsArticleDataBean.class, new NewsArticleVideoViewBinder());
adapter.register(LoadingBean.class, new LoadingViewBinder());
adapter.register(LoadingEndBean.class, new LoadingEndViewBinder());
}
3.6.最后再DiffCallback中加视频类型
在areItemsTheSame函数中添加Video类型。
因为类型和Multi_News一样,用这个代替也一样。
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();
4.视图绑定类
4.1.视图绑定类的布局定义==>item_news_article_video.xml
<?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>
4.2.视图效果
4.3.视图绑定类
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);
}
}
}
这个绑定类和新闻中的页面的其中一种类型完全一样。
因为新闻页面中有3种类型,一种纯文字,一种图片,一种视频。
这里就直接用新闻中的视频的绑定类即可。
因为API也是用的新闻
可以说视频这个大类,就是从新闻中筛选出的视频类型。
通过传入的一个参数category,返回的全是视频。
5.目前效果预览
5.1.目前完成的工作
新闻的三种大类型
图片的一种大类型,这种大类型有4个分类,为全部、老照片、故事照片和摄影集。
视频采用的是新闻中的其中一种大类型,所以直接用新闻中的绑定类即可,API也一样的。
但是每种类型的评论以及详细页面还未实现。
5.2.手机真实数据预览
TouTiao开源项目 分析笔记12 从总体到局部 构建视频主页面的更多相关文章
- TouTiao开源项目 分析笔记11 以总体到局部的思路 构建图片主列表
1.构建图片主列表的整体片段PhotoTabLayout 1.1.首先创建一个PhotoTabLayout片段 public class PhotoTabLayout extends Fragment ...
- TouTiao开源项目 分析笔记13 最后一个订阅号的实现主页面
1.实现订阅号的基础类 1.1.本地订阅号的Bean类==>MediaChannelBean public class MediaChannelBean implements Parcelabl ...
- TouTiao开源项目 分析笔记2
1.Constant常量定义类 1.1.源代码 public class Constant { public static final String USER_AGENT_MOBILE = " ...
- TouTiao开源项目 分析笔记4==>一个简单APP 整体常用框架
1.效果预览 1.1.如下图所以,到目前为止所有的功能. 2.从InitApp开始->SplashActivity->MainActivity 2.1.InitApp源代码.这是整个项目的 ...
- TouTiao开源项目 分析笔记6
1.NewsChannelBean简单类笔记 1.1.Comparable接口的实现和使用 参考文章:Comparable接口的实现和使用. 因为NewsChannelBean实现了Comparabl ...
- TouTiao开源项目 分析笔记15 新闻详情之两种类型的实现
1.预览效果 1.1.首先看一下需要实现的效果. 第一种,文字类型新闻. 第二种,图片类型新闻. 1.2.在NewsArticleTextViewBinder中设置了点击事件 RxView.click ...
- TouTiao开源项目 分析笔记10 实现通用普通文章片段页面
1.RxJava的Observable数据操作符总结 1.1.Map操作符 Map操作符对原始Observable发射的没一项数据应用一个你选择的函数, 然后返回一个发射这些结果的Observable ...
- TouTiao开源项目 分析笔记18 视频详情页面
1.效果预览 1.1.需要做到的真实效果 1.2.触发的点击事件 在MediaArticleVideoViewBinder的每一个item点击事件中: VideoContentActivity.lau ...
- TouTiao开源项目 分析笔记17 新闻媒体专栏
1.效果预览 1.1.要实现的效果 1.2.如何调转到新闻媒体专栏 点击右上角的用户图标. 在新闻详情页面的Fragment的菜单点击事件中触发. case R.id.action_open_medi ...
随机推荐
- Android Studio Git 分支实践
新公司有些项目是用的 Git,以前公司都是 svn,为了练手 Git,我个人 APP 用到了,但是仅简单的 git pull/push 的使用,并未用到 Git 精髓,只有当项目中用到,才会紧迫去全面 ...
- android studio gradle统一管理版本
创建config.gradle ext { android = [ compileSdkVersion : 26, buildToolsVersion : "26.0.2", mi ...
- 【技巧】如何使用UltraEdit删掉某些行并且不留空行
例: 在S1这个文件中我想要把所有B6 96 FD 2E 49 96 2 D2的行删掉. 首先,查找这些序列,执行替换命令,替换为的内容不写. 点击“全部替换”之后,发现在原来的位置多了一行空行. 接 ...
- 炫酷的Html+css (一)
博客园在别的 博主看到一个样式, 里面有一段这样的 正方体旋转的 动态图 吸引了我. 找博主要了代码, 贴出来 与大家共享. 鼠标放上去会展开 一大一小两个正方体, 鼠标悬浮上去, 外面的正方体会展开 ...
- [转载]在VB.Net中获取COM对象的特定实例(Getting a specific instance of COM object in VB.Net)
转载:http://www.it1352.com/534235.html 问题: I am writing a Windows Form application in .Net to list all ...
- pat甲级1085
1085 Perfect Sequence (25 分) Given a sequence of positive integers and another positive integer p. T ...
- py常见模块
1.系统相关的信息模块: import sys sys.argv 是一个 list,包含所有的命令行参数. sys.stdout sys.stdin sys.stderr 分别表示标准输入输出,错误输 ...
- python IDE-pycharm在virtualenv里安装软件
1 windows命令行,进入venv下的scripts目录,执行activate.bat进入虚拟环境 2 以selenium安装为例,输入pip install selenium回车开始安装 3 ...
- 尝试将 SCRIPT ompbox\private\ompmex 作为函数执行
1.安装VS2010 2.配置ombox 在ombox路径下 mex -setup C++ 然后 make
- Vue路由讲解
1>router-link和router-view组件 2>路由配置 a.动态路由 import Home from "@/views/Home.vue"; expor ...