TouTiao开源项目 分析笔记14 段子评论

Posted Jason_Jan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TouTiao开源项目 分析笔记14 段子评论相关的知识,希望对你有一定的参考价值。


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"TouTiao开源项目 分析笔记4

TouTiao开源项目 分析笔记7

TouTiao开源项目 分析笔记19 问答内容

TouTiao开源项目 分析笔记5

TouTiao开源项目 分析笔记9 实现一个问答主页面

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