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 从总体到局部 构建视频主页面的更多相关文章

  1. TouTiao开源项目 分析笔记11 以总体到局部的思路 构建图片主列表

    1.构建图片主列表的整体片段PhotoTabLayout 1.1.首先创建一个PhotoTabLayout片段 public class PhotoTabLayout extends Fragment ...

  2. TouTiao开源项目 分析笔记13 最后一个订阅号的实现主页面

    1.实现订阅号的基础类 1.1.本地订阅号的Bean类==>MediaChannelBean public class MediaChannelBean implements Parcelabl ...

  3. TouTiao开源项目 分析笔记2

    1.Constant常量定义类 1.1.源代码 public class Constant { public static final String USER_AGENT_MOBILE = " ...

  4. TouTiao开源项目 分析笔记4==>一个简单APP 整体常用框架

    1.效果预览 1.1.如下图所以,到目前为止所有的功能. 2.从InitApp开始->SplashActivity->MainActivity 2.1.InitApp源代码.这是整个项目的 ...

  5. TouTiao开源项目 分析笔记6

    1.NewsChannelBean简单类笔记 1.1.Comparable接口的实现和使用 参考文章:Comparable接口的实现和使用. 因为NewsChannelBean实现了Comparabl ...

  6. TouTiao开源项目 分析笔记15 新闻详情之两种类型的实现

    1.预览效果 1.1.首先看一下需要实现的效果. 第一种,文字类型新闻. 第二种,图片类型新闻. 1.2.在NewsArticleTextViewBinder中设置了点击事件 RxView.click ...

  7. TouTiao开源项目 分析笔记10 实现通用普通文章片段页面

    1.RxJava的Observable数据操作符总结 1.1.Map操作符 Map操作符对原始Observable发射的没一项数据应用一个你选择的函数, 然后返回一个发射这些结果的Observable ...

  8. TouTiao开源项目 分析笔记18 视频详情页面

    1.效果预览 1.1.需要做到的真实效果 1.2.触发的点击事件 在MediaArticleVideoViewBinder的每一个item点击事件中: VideoContentActivity.lau ...

  9. TouTiao开源项目 分析笔记17 新闻媒体专栏

    1.效果预览 1.1.要实现的效果 1.2.如何调转到新闻媒体专栏 点击右上角的用户图标. 在新闻详情页面的Fragment的菜单点击事件中触发. case R.id.action_open_medi ...

随机推荐

  1. Android Studio Git 分支实践

    新公司有些项目是用的 Git,以前公司都是 svn,为了练手 Git,我个人 APP 用到了,但是仅简单的 git pull/push 的使用,并未用到 Git 精髓,只有当项目中用到,才会紧迫去全面 ...

  2. android studio gradle统一管理版本

    创建config.gradle ext { android = [ compileSdkVersion : 26, buildToolsVersion : "26.0.2", mi ...

  3. 【技巧】如何使用UltraEdit删掉某些行并且不留空行

    例: 在S1这个文件中我想要把所有B6 96 FD 2E 49 96 2 D2的行删掉. 首先,查找这些序列,执行替换命令,替换为的内容不写. 点击“全部替换”之后,发现在原来的位置多了一行空行. 接 ...

  4. 炫酷的Html+css (一)

    博客园在别的 博主看到一个样式, 里面有一段这样的 正方体旋转的 动态图 吸引了我. 找博主要了代码, 贴出来 与大家共享. 鼠标放上去会展开 一大一小两个正方体, 鼠标悬浮上去, 外面的正方体会展开 ...

  5. [转载]在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 ...

  6. pat甲级1085

    1085 Perfect Sequence (25 分) Given a sequence of positive integers and another positive integer p. T ...

  7. py常见模块

    1.系统相关的信息模块: import sys sys.argv 是一个 list,包含所有的命令行参数. sys.stdout sys.stdin sys.stderr 分别表示标准输入输出,错误输 ...

  8. python IDE-pycharm在virtualenv里安装软件

    1  windows命令行,进入venv下的scripts目录,执行activate.bat进入虚拟环境 2  以selenium安装为例,输入pip install selenium回车开始安装 3 ...

  9. 尝试将 SCRIPT ompbox\private\ompmex 作为函数执行

    1.安装VS2010 2.配置ombox 在ombox路径下 mex -setup C++ 然后 make

  10. Vue路由讲解

    1>router-link和router-view组件 2>路由配置 a.动态路由 import Home from "@/views/Home.vue"; expor ...