1.段子页面详情

1.1.先看看预览界面吧

  

  左边的页面已经实现了,现在的目的就是要实现点击左侧的每一个item

  然后跳转到右边相应的段子详情页面。

1.2.首先肯定有右侧这个活动==>JokeCommentActivity。

  外部如何启动?

fun launch(bean: JokeContentBean.DataBean.GroupBean) {
InitApp.AppContext.startActivity(Intent(InitApp.AppContext, JokeCommentActivity::class.java)
.putExtra(TAG, bean)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
}

  这个Intent.FLAG_ACTIVITY_NEW_TASK是什么意思?

  ——在这里的意思,从Activity A到Activity B的过程中,将Activity B加到Activity A的任务堆栈中。

     然后按返回键,即回退到Activity A中了。

  更多详解参见这篇文章:Android Intent.FLAG_ACTIVITY_NEW_TASK详解。

1.3.这个JokeCommentActivity布局是怎么的呢? 

<FrameLayout
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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/viewBackground"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:layout="@layout/fragment_news_tab"/>

  so easy!

  just a FrameLayout.

1.4.然后用什么来替换这个FrameLayout呢?

 override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.container)
supportFragmentManager.beginTransaction().replace(R.id.container,一个片段来代替).commit()
}

1.5.紧接着,就是来构造这个片段了。

  段子评论接口: 

public interface IJokeComment {
interface View extends IBaseListView<Presenter> { /**
* 请求数据
*/
void onLoadData();
} interface Presenter extends IBasePresenter { /**
* 请求数据
*/
void doLoadData(String... jokeId_Count); /**
* 再起请求数据
*/
void doLoadMoreData(); /**
* 设置适配器
*/
void doSetAdapter(List<JokeCommentBean.DataBean.RecentCommentsBean> commentsBeanList); /**
* 加载完毕
*/
void doShowNoMore();
}
}

  一个用于视图方面的函数。

  一个用于处理器方面的函数。

1.6.这个段子详情的布局是怎样的呢?

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/windowBackground"
android:fitsSystemWindows="true"
android:orientation="vertical"> <include layout="@layout/toolbar"/> <android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fadeScrollbars="true"
android:scrollbarFadeDuration="1"
android:scrollbars="vertical"
app:layoutManager="LinearLayoutManager">
</android.support.v7.widget.RecyclerView> </android.support.v4.widget.SwipeRefreshLayout> </android.support.design.widget.CoordinatorLayout>

  预览页面是这样的:

  

1.7.Intent.createChooser(intent)应用选择器的理解

  一般用于分享的时候,可以用这样方法,用来选择哪个应用来分享。

  Intent intent=new Intent();

  startActivity(Intent.createChooser(intent));

  可以弹出一个小框,然后进行相应的选择即可。

2.定义段子详情片段

2.1.源代码==>JokeCommentFragment

package com.jasonjan.headnews.module.joke.comment;

import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import com.jasonjan.headnews.R;
import com.jasonjan.headnews.adapter.DiffCallback;
import com.jasonjan.headnews.bean.common.LoadingBean;
import com.jasonjan.headnews.bean.joke.JokeContentBean;
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 2018/1/7.
*/ public class JokeCommentFragment extends BaseListFragment<IJokeComment.Presenter> implements IJokeComment.View { public static final String TAG = "JokeCommentFragment";
private String jokeId;
private String jokeCommentCount;
private String jokeText;
private JokeContentBean.DataBean.GroupBean jokeCommentHeaderBean; public static JokeCommentFragment newInstance(Parcelable data) {
Bundle args = new Bundle();
args.putParcelable(TAG, data);
JokeCommentFragment fragment = new JokeCommentFragment();
fragment.setArguments(args);
return fragment;
} @Override
protected int attachLayoutId() {
return R.layout.fragment_list_toolbar;
} @Override
protected void initView(View view) {
super.initView(view);
Toolbar toolbar = view.findViewById(R.id.toolbar);
initToolBar(toolbar, true, "");
toolbar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
recyclerView.smoothScrollToPosition(0);
}
}); adapter = new MultiTypeAdapter(oldItems);
Register.registerJokeCommentItem(adapter);
recyclerView.setAdapter(adapter);
recyclerView.addOnScrollListener(new OnLoadMoreListener() {
@Override
public void onLoadMore() {
if (canLoadMore) {
canLoadMore = false;
presenter.doLoadMoreData();
}
}
});
setHasOptionsMenu(true);
} @Override
protected void initData() {
Bundle bundle = getArguments();
try {
jokeCommentHeaderBean = bundle.getParcelable(TAG);
jokeId = jokeCommentHeaderBean.getId() + "";
jokeCommentCount = jokeCommentHeaderBean.getComment_count() + "";
jokeText = jokeCommentHeaderBean.getText();
oldItems.add(jokeCommentHeaderBean);
} catch (Exception e) { }
onLoadData();
} @Override
public void onLoadData() {
presenter.doLoadData(jokeId, jokeCommentCount);
} @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_joke_comment, menu);
super.onCreateOptionsMenu(menu, inflater);
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_comment_share:
Intent shareIntent = new Intent()
.setAction(Intent.ACTION_SEND)
.setType("text/plain")
.putExtra(Intent.EXTRA_TEXT, jokeText);
startActivity(Intent.createChooser(shareIntent, getString(R.string.share_to)));
break;
}
return super.onOptionsItemSelected(item);
} @Override
public void onRefresh() {
presenter.doRefresh();
} @Override
public void onSetAdapter(final List<?> list) {
Items newItems = new Items();
newItems.add(jokeCommentHeaderBean);
newItems.addAll(list);
newItems.add(new LoadingBean());
DiffCallback.notifyDataSetChanged(oldItems, newItems, DiffCallback.JOKE_COMMENT, adapter);
oldItems.clear();
oldItems.addAll(newItems);
canLoadMore = true;
} @Override
public void setPresenter(IJokeComment.Presenter presenter) {
if (null == presenter) {
this.presenter = new JokeCommentPresenter(this);
}
} @Override
public void fetchData() { }
}

2.2.定义了外部新建这个实例的一个静态方法。

  

2.3.实现抽象方法,返回这个片段的整体布局,包括toolbar。

2.4.初始化视图,定义适配器+recyclerView滑动监听事件+分享菜单。

2.5.初始化数据,在最开始新建的实例中,传递了一个序列化,

  这里将这个序列化的数据加到oldItems中。

  然后调用onLoadData方法来加载数据。

2.6. 定义onLoadData方法,调用处理器的doLoadData方法。

2.7.定义分享菜单的布局,自定义一个图标即可。

2.8.实现分享菜单的点击事件。

2.9.定义刷新事件,调用处理器的doRefresh()。

2.10.设置处理器,这里需要一个自定义的处理器。

3.自定义处理器

3.1.源代码 

package com.jasonjan.headnews.module.joke.comment;

import com.jasonjan.headnews.api.IJokeApi;
import com.jasonjan.headnews.bean.joke.JokeCommentBean;
import com.jasonjan.headnews.main.ErrorAction;
import com.jasonjan.headnews.main.RetrofitFactory; import java.util.ArrayList;
import java.util.List; import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers; /**
* Created by JasonJan on 2018/1/7.
*/ public class JokeCommentPresenter implements IJokeComment.Presenter{ private IJokeComment.View view;
private String jokeId;
private int count = -1;
private int offset = 0;
private List<JokeCommentBean.DataBean.RecentCommentsBean> commentsList = new ArrayList<>(); JokeCommentPresenter(IJokeComment.View view) {
this.view = view;
} @Override
public void doLoadMoreData() {
offset += 10;
doLoadData();
} @Override
public void doLoadData(String... jokeId_Count) { try {
if (null == this.jokeId) {
this.jokeId = jokeId_Count[0];
}
if (-1 == this.count) {
this.count = Integer.parseInt(jokeId_Count[1]);
}
} catch (Exception e) {
ErrorAction.print(e);
} RetrofitFactory.getRetrofit().create(IJokeApi.class).getJokeComment(jokeId, offset)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.map(new Function<JokeCommentBean, List<JokeCommentBean.DataBean.RecentCommentsBean>>() {
@Override
public List<JokeCommentBean.DataBean.RecentCommentsBean> apply(@NonNull JokeCommentBean jokeCommentBean) throws Exception {
return jokeCommentBean.getData().getRecent_comments();
}
})
.compose(view.<List<JokeCommentBean.DataBean.RecentCommentsBean>>bindToLife())
.subscribe(new Consumer<List<JokeCommentBean.DataBean.RecentCommentsBean>>() {
@Override
public void accept(@NonNull List<JokeCommentBean.DataBean.RecentCommentsBean> recentCommentsBeen) throws Exception {
if (recentCommentsBeen.size() > 0) {
doSetAdapter(recentCommentsBeen);
} else {
doShowNoMore();
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
doShowNetError();
ErrorAction.print(throwable);
}
});
} @Override
public void doSetAdapter(List<JokeCommentBean.DataBean.RecentCommentsBean> commentsBeanList) {
commentsList.addAll(commentsBeanList);
view.onSetAdapter(commentsList);
view.onHideLoading();
} @Override
public void doRefresh() {
if (commentsList.size() != 0) {
commentsList.clear();
offset = 0;
}
doLoadData();
} @Override
public void doShowNetError() {
view.onHideLoading();
view.onShowNetError();
} @Override
public void doShowNoMore() {
view.onHideLoading();
if (commentsList.size() > 0) {
view.onShowNoMore();
}
} }

3.2.首先一个构造函数,传递一个视图类型进去。

3.3.重写加载更多doLoadMoreData()。

3.4.重写加载数据doLoadData(String... jokeId_Count)。

3.5.重写设置适配器,交给视图的onSetAdapter来完成。

3.6.重写刷新函数doRefresh()函数,调用了doLoadData()函数。

3.7.重写显示网络错误,交给视图的onShowNetError来完成。

3.8.重写显示没有更多了,交给视图的onShowNoMore来完成。

4.注册数据类型

4.1.首先在Register中定义一个静态函数。  

 /**
* 段子评论
* @param adapter
*/
public static void registerJokeCommentItem(@NonNull MultiTypeAdapter adapter) {
adapter.register(JokeContentBean.DataBean.GroupBean.class, new JokeCommentHeaderViewBinder());
adapter.register(JokeCommentBean.DataBean.RecentCommentsBean.class, new JokeCommentViewBinder());
adapter.register(LoadingBean.class, new LoadingViewBinder());
adapter.register(LoadingEndBean.class, new LoadingEndViewBinder());
}

4.2.定义JokeCommentHeaderViewBinder

  定义头部视图绑定。  

public class JokeCommentHeaderViewBinder extends ItemViewBinder<JokeContentBean.DataBean.GroupBean,JokeCommentHeaderViewBinder.ViewHolder>{
@NonNull
@Override
protected JokeCommentHeaderViewBinder.ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) {
View view = inflater.inflate(R.layout.item_joke_content, parent, false);
return new ViewHolder(view);
} @Override
protected void onBindViewHolder(@NonNull final ViewHolder holder, @NonNull final JokeContentBean.DataBean.GroupBean item) { final Context context = holder.itemView.getContext(); try {
String avatar_url = item.getUser().getAvatar_url();
String name = item.getUser().getName();
String text = item.getText();
String digg_count = item.getDigg_count() + "";
String bury_count = item.getBury_count() + "";
int comment_count = item.getComment_count(); ImageLoader.loadCenterCrop(context, avatar_url, holder.iv_avatar, R.color.viewBackground);
holder.tv_username.setText(name);
holder.tv_text.setText(text);
holder.tv_digg_count.setText(digg_count);
holder.tv_bury_count.setText(bury_count);
if (comment_count > 0) {
holder.tv_comment_count.setText(comment_count + "评论");
} else {
holder.tv_comment_count.setVisibility(View.GONE);
}
holder.iv_dots.setVisibility(View.GONE); holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final String content = item.getText();
final BottomSheetDialogFixed dialog = new BottomSheetDialogFixed(context);
dialog.setOwnerActivity((BaseActivity) context);
View view = ((BaseActivity) context).getLayoutInflater().inflate(R.layout.item_comment_action_sheet, null);
view.findViewById(R.id.layout_copy_text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ClipboardManager copy = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData = ClipData.newPlainText("text", content);
copy.setPrimaryClip(clipData);
Snackbar.make(holder.itemView, R.string.copied_to_clipboard, Snackbar.LENGTH_SHORT).show();
dialog.dismiss();
}
});
view.findViewById(R.id.layout_share_text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
IntentAction.send(context, content);
dialog.dismiss();
}
});
dialog.setContentView(view);
dialog.show();
}
});
} catch (Exception e) {
ErrorAction.print(e);
}
} class ViewHolder extends RecyclerView.ViewHolder { private CircleImageView iv_avatar;
private TextView tv_username;
private TextView tv_text;
private TextView tv_digg_count;
private TextView tv_bury_count;
private TextView tv_comment_count;
private ImageView iv_dots; ViewHolder(View itemView) {
super(itemView);
this.iv_avatar = itemView.findViewById(R.id.iv_avatar);
this.tv_username = itemView.findViewById(R.id.tv_username);
this.tv_text = itemView.findViewById(R.id.tv_text);
this.tv_digg_count = itemView.findViewById(R.id.tv_digg_count);
this.tv_bury_count = itemView.findViewById(R.id.tv_bury_count);
this.tv_comment_count = itemView.findViewById(R.id.tv_comment_count);
this.iv_dots = itemView.findViewById(R.id.iv_dots);
}
}
}

  每个item的样式==>item_joke_content

  

<?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="match_parent"
android:background="?attr/selectableItemBackground"
android:foreground="?attr/selectableItemBackground"
android:orientation="vertical"
android:padding="16dp"> <LinearLayout
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"> <com.jasonjan.headnews.widget.CircleImageView
android:id="@+id/iv_avatar"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_gravity="center"/> <TextView
android:id="@+id/tv_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
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="小恢恢的帽子"/> <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: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_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="昨天和闺蜜出去逛街,闺密问她老公要钱,她老公坐在沙发上,翘着二郎腿抽着烟问:“20行吗?”闺密想了想,温柔的点点头,我正惊讶她老公能把她管制的服服贴贴,只见她老公从钱包里掏出20,然后把钱包递给了媳妇……"/> <LinearLayout
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_gravity="bottom"
android:layout_marginTop="6dp"
android:gravity="bottom"
android:orientation="horizontal"> <TextView
android:id="@+id/tv_digg_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="53"/> <ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
app:srcCompat="@drawable/ic_like_gray_24dp"
tools:ignore="ContentDescription"/> <TextView
android:id="@+id/tv_bury_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
tools:text="11"/> <ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
app:srcCompat="@drawable/ic_dislike_gray_24dp"
tools:ignore="ContentDescription"/> <TextView
android:id="@+id/tv_comment_count"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
tools:text="48评论"/> </LinearLayout> </LinearLayout> </RelativeLayout>
</android.support.v7.widget.CardView>

  预览图片:

  

4.3.定义评论的视图绑定==>JokeCommentViewBinder

package com.jasonjan.headnews.binder.joke;

import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView; import com.jasonjan.headnews.R;
import com.jasonjan.headnews.bean.joke.JokeCommentBean;
import com.jasonjan.headnews.main.ErrorAction;
import com.jasonjan.headnews.main.IntentAction;
import com.jasonjan.headnews.module.base.BaseActivity;
import com.jasonjan.headnews.util.ImageLoader;
import com.jasonjan.headnews.widget.BottomSheetDialogFixed;
import com.jasonjan.headnews.widget.CircleImageView; import me.drakeet.multitype.ItemViewBinder; /**
* Created by Meiji on 2017/6/10.
*/ public class JokeCommentViewBinder extends ItemViewBinder<JokeCommentBean.DataBean.RecentCommentsBean, JokeCommentViewBinder.ViewHolder> { @NonNull
@Override
protected JokeCommentViewBinder.ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) {
View view = inflater.inflate(R.layout.item_joke_comment, parent, false);
return new ViewHolder(view);
} @Override
protected void onBindViewHolder(@NonNull final ViewHolder holder, @NonNull final JokeCommentBean.DataBean.RecentCommentsBean item) { final Context context = holder.itemView.getContext(); try {
String iv_avatar = item.getUser_profile_image_url();
String tv_username = item.getUser_name();
String tv_text = item.getText();
String tv_likes = item.getDigg_count() + "赞"; ImageLoader.loadCenterCrop(context, iv_avatar, holder.iv_avatar, R.color.viewBackground);
holder.tv_username.setText(tv_username);
holder.tv_text.setText(tv_text);
holder.tv_likes.setText(tv_likes);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final String content = item.getText();
final BottomSheetDialogFixed dialog = new BottomSheetDialogFixed(context);
dialog.setOwnerActivity((BaseActivity) context);
View view = ((BaseActivity) context).getLayoutInflater().inflate(R.layout.item_comment_action_sheet, null);
view.findViewById(R.id.layout_copy_text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ClipboardManager copy = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData = ClipData.newPlainText("text", content);
copy.setPrimaryClip(clipData);
Snackbar.make(holder.itemView, R.string.copied_to_clipboard, Snackbar.LENGTH_SHORT).show();
dialog.dismiss();
}
});
view.findViewById(R.id.layout_share_text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
IntentAction.send(context, content);
dialog.dismiss();
}
});
dialog.setContentView(view);
dialog.show();
}
});
} catch (Exception e) {
ErrorAction.print(e);
}
} class ViewHolder extends RecyclerView.ViewHolder { private CircleImageView iv_avatar;
private TextView tv_username;
private TextView tv_text;
private TextView tv_likes; ViewHolder(View itemView) {
super(itemView);
this.iv_avatar = itemView.findViewById(R.id.iv_avatar);
this.tv_username = itemView.findViewById(R.id.tv_username);
this.tv_text = itemView.findViewById(R.id.tv_text);
this.tv_likes = itemView.findViewById(R.id.tv_likes);
}
}
}

  每个item的视图布局==>item_joke_comment 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/viewBackground"> <LinearLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:foreground="?attr/selectableItemBackground"
android:orientation="vertical"
android:paddingBottom="8dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"> <com.jasonjan.headnews.widget.CircleImageView
android:id="@+id/iv_avatar"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_gravity="center"/> <TextView
android:id="@+id/tv_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:ellipsize="end"
tools:text="小恢恢的帽子"/> </LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:orientation="vertical"> <TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="最恨公共场所吸烟的。特别是在饭店。电梯等一些空气不流通的环境"/> <TextView
android:id="@+id/tv_likes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:gravity="end"
android:maxLines="1"
tools:text="4832赞"/> </LinearLayout> </LinearLayout> <View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_below="@+id/content"
android:background="@color/line_divider"/> </RelativeLayout>

  预览图片:

  

5.处理API

5.1.在处理器中怎么调用的呢?

 RetrofitFactory.getRetrofit().create(IJokeApi.class)
                  .getJokeComment(jokeId, offset)
                  ....

5.2.所以在实际的API中是怎样的呢? 

public interface IJokeApi {

    /**
* 获取段子正文内容
* http://www.toutiao.com/api/article/feed/?category=essay_joke&as=A115C8457F69B85&cp=585F294B8845EE1
*/
@GET("api/article/feed/?category=essay_joke")
Observable<JokeContentBean> getJokeContent(
@Query("max_behot_time") String maxBehotTime,
@Query("as") String as,
@Query("cp") String cp); /**
* 获取段子评论
* http://m.neihanshequ.com/api/get_essay_comments/?group_id=编号&count=数量&offset=偏移量
*/
@GET("http://m.neihanshequ.com/api/get_essay_comments/?count=20")
@Headers({"User-Agent:" + Constant.USER_AGENT_MOBILE})
Observable<JokeCommentBean> getJokeComment(
@Query("group_id") String groupId,
@Query("offset") int offset);
}

  groupId==>段子的唯一标识符。

  offset==>评论的分页处理

6.新老数据处理

6.1.在JokeCommentFragmentsh中设置适配器的时候

  要进行新老数据处理。

  这里调用方式很简单。

 @Override
public void onSetAdapter(final List<?> list) {
Items newItems = new Items();
newItems.add(jokeCommentHeaderBean);
newItems.addAll(list);
newItems.add(new LoadingBean());
DiffCallback.notifyDataSetChanged(oldItems, newItems, DiffCallback.JOKE_COMMENT, adapter);
oldItems.clear();
oldItems.addAll(newItems);
canLoadMore = true;
}

6.2.所以在自定义DiffCallback中注册这种类型即可。

  在areItemsTheSame函数中,加一个JOKE_COMMENT 

  case JOKE_COMMENT:
return ((JokeCommentBean.DataBean.RecentCommentsBean) oldList.get(oldItemPosition)).getText().equals(
((JokeCommentBean.DataBean.RecentCommentsBean) newList.get(newItemPosition)).getText());

6.3.在areContentsTheSame函数中,加一个JOKE_COMMENT

 case JOKE_COMMENT:
return ((JokeCommentBean.DataBean.RecentCommentsBean) oldList.get(oldItemPosition)).getId() ==
((JokeCommentBean.DataBean.RecentCommentsBean) newList.get(newItemPosition)).getId();

6.4.因为这个API不稳定,这里就不进行实际页面展示了。

TouTiao开源项目 分析笔记14 段子评论的更多相关文章

  1. TouTiao开源项目 分析笔记16 新闻评论

    1.要达到的效果 1.1.主要效果图 点击了标题栏的消息图标后,然后会跳转到评论详情的页面. 1.2.触发的点击事件 在新闻详情的片段中的菜单点击事件中 设置上方标题栏的消息标的监听事件 case R ...

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

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

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

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

  4. TouTiao开源项目 分析笔记12 从总体到局部 构建视频主页面

    1.构建视频主列表的整体碎片VideoTabLayout 1.1.首先创建一个VideoTabLayout package com.jasonjan.headnews.module.video; im ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 树checkbox选择jquery实例

    <!DOCTYPE html> <html> <head> <title></title> <script src="htt ...

  2. VC++ MFC类库基础(55讲全)

    视频保存在播音员 网盘中内容简介: 本部分是您成为VC++软件工程师必备的阶段,如果您没有任何基础,学习C++能快速让您进入编程领域,建议配合书籍<C++入门经典> 关键词: VC++.V ...

  3. April 13 2017 Week 15 Thursday

    Happiness takes no account of time. 幸福不觉光阴过. Do you know the theory of relativity? If you know about ...

  4. SQL SERVER 下:1、递归查询父分类下的各个子分类。 2、查询每个商品分类中最贵的前两个商品SQL

    1.递归查询父分类下的各个子分类.表设计: SQL: --CTE 语句(适用于MSSQL2005以后版本) with cte_testNavi(Id,Name,Pid ) as ( --这是查询语句 ...

  5. 使用selenium grid的hub做分发,且可查看分发后的服务器IP地址

    背景:借助selenium 的grid做分布式运行,进行分发任务,(目前不做多浏览器的操作,只对谷歌浏览器进行操作) 目前在A服务器(http://10.40.6.24:4444)上注册了一个hub, ...

  6. LA 5031 图询问

    题目链接:https://vjudge.net/contest/159527#problem/A 题意:(求一个 图 中的连通分量中的 第 k 大) 一张图,n 个点,m 条边, 有一些操作: 删除 ...

  7. Codeforces Round #347 (Div.2)_B. Rebus

    题目链接:http://codeforces.com/contest/664/problem/B B. Rebus time limit per test 1 second memory limit ...

  8. 2017.10.16 java中getAttribute和getParameter的区别

    (1)getAttribute:表示得到 域中的对象 返回的是OBJ类型;  getParameter:表示 得到 传递的参数 返回的是String类型; 也就是getAttribute获得的值需要进 ...

  9. 2017.9.28 web设计简单的购物车应用案例--session的简单应用

    该购物过程是在session范围内完成的,需要使用session对象实现信息的共享 (1)购买“肉类”商品的页面 <%@ page language="java" impor ...

  10. CSS font-size字体大小样式属性

    设置字体大小CSS单词与语法 基本语法结构: .divcss5{font-size:12px;}设置了文字大小为12px像素Font-size+字体大小数值+单位 单词:font-size语法:fon ...