章节中所有代码和笔记均参考、摘录自《第一行代码(第二版)》
照着书写好的Demo疯狂闪退,找两个错漏找了一个多小时,真的整个人都裂开。 Fragment和RecyclerView真的只要一段时间没看(几个月前才看过),马上就能忘干净,看来纯看书确实没什么鬼用。
好吧,Fragment一般是平板开发使用的,我理解为Activity青春版,通过Fragment分割屏幕使得内容得以充分的展示,最大化利用平板屏幕大的优点。
创建自定义的Fragment并继承Fragment,在里面重写 onCreateView() 方法,然后通过
inflater.inflate(R.layout.left_fragment, container, false);
将left_layout(这里是layout的名称)动态加载进入。
为什么重写的是 onCreateView() ?
放上网上找到的Fragment的生命周期图看一下

onAttach() 在Fragment和Activity建立关联调用,而且碎片和活动是最先绑定,最后解绑。在碎片创建之后就调用 onCreateView()创建视图了,由此重写onCreateView()载入自定义布局(记得要返回view)。至于onActivityCreated() 如其名一样,在碎片和相关活动创建完毕的时候调用。
好的,既然对自定义碎片布局需要创建一个类并继承Fragment,那么双页模式(两个碎片)就自定义两个碎片类。

上图中,
News为实体类(Java Bean,包含String类型数据Title和Context及其方法)。
NewsContentFragment除了填充布局以外,就实现了一个refresh()用来对布局中的两个TextView控件赋值。
NewsContentActivity实现了actionStart方便其他类调用intent调转向本类并传递news_title、news_content两个参数,在onCreate()方法中,获取intent传入的参数,并通过
getSupportFragmentManager().findFragmentById(R.id.news_content_fragment);
创建并获取NewsContentFragment实例,调用其refresh()刷新界面。
NewsTitleFragment是展示新闻列表的碎片,除了填充布局之外,添加了一个名为isTwoPane的布尔值,在碎片和活动都成功创建时(onActivityCreated()),判断是否为双页布局来调整这个布尔值。
NewsTitleFragment类还实现了一个NewsAdapter的内部类,用来作为RecyclerView的适配器。这个适配器和之前RecycerView部分的几乎相同,但是还是单独放出来,因为刚开始看到确实这部分是最难消化的。
class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder>{ private List<News> mNewsList; class ViewHolder extends RecyclerView.ViewHolder{ TextView newsTitleText; public ViewHolder(View view){ super(view); newsTitleText = view.findViewById(R.id.news_title); } } public NewsAdapter(List<News> newsList){ mNewsList = newsList; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.news_item,parent,false); final ViewHolder holder = new ViewHolder(view); view.setOnClickListener(view1 -> { News news = mNewsList.get(holder.getAdapterPosition()); if(isTwoPane){ NewsContentFragment newsContentFragment = (NewsContentFragment) getFragmentManager().findFragmentById(R.id.news_content_fragment); newsContentFragment.refresh(news.getTitle(),news.getContent()); }else{ NewsContentActivity.actionStart(getActivity(),news.getTitle(),news.getContent()); } }); return holder; } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { News news = mNewsList.get(position); holder.newsTitleText.setText(news.getTitle()); } @Override public int getItemCount() { return mNewsList.size(); } }

如上图所见,下面说一下布局文件。
MainActivity在其对应的layout文件里只有一个碎片。当然,为了手机和平板都能合适的使用此应用,在layout文件夹下新建了layout-sw600dp,并在其中创建了同样名为activity_main的布局文件,此布局是在平板打开应用时载入的布局。
news_item很好理解,就是作为RecyclerView的子布局,而new_title_frag里面也只有一个RecyclerView,这两个通过NewsAdapter组合到一起,完成点击并在news_content_frag中显示的功能。
news_content_frag就是右侧新闻内容碎片的布局。
news_content就是单页模式中点击news_title_frag所显示的布局,直接复用news_content_frag的布局。如下图所示,可以看到平板右侧和手机点击后布局是一样的。

