<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    RecyclerView Part 1:为ListView专家写的基础

    原文链接? ? 作者:Bill Phillips ? ?译者:赵峰

    是时候讲清楚了:我了解RecylerView有些晚。太迟了。

    这只能怪我自己。你可以从文档中得知RecylerView应该会取代ListView,并且在工具包里没有几个视图比ListView更重要。所以,RecyclerView十分重要。

    但是它们还是会有很多不同,对吗?嗯。所以我一直推迟对它的讲解,直到几周之前我为Hack Night准备一个讲座的时候。我最终做了大量的研究,我承认这些研究很有乐趣。

    最终的结果是RecyclerView非???,值的去替换listView。它把以前非常棘手的东西变的非常非常简单。最重要的是,它可以让一个item轻松的从一个可行的列表中动画流入和流出,而不像之前那样慢。

    通过指出所有的这些要点,我决定把ListView从我们的 Android programming guide中删除,并用RecyclerView代替。我发现使用RecyclerView会使大多数的工作变的非常容易,并且最终的代码非常简洁。

    除了一点:选择模式(choice modes)。setChoiceMode()被去掉了,并且让一个RecyclerView转换多项选择,会导致了一些有趣的问题。在以后的几篇博客中我将会按照步骤来跟你分享我的解决方案。在这里我先从RecyclerView的基本用法开始。

    RecyclerView做的更少
    如果你打算替换ListView,那么现在让我们讨论下RecyclerView中的一些重大变化。
    第1步,当然这是非常重要的,你需要在build.gradle里写入下面这一行:
    compile ‘com.android.support:recyclerview-v7:+’

    第二步:有一个很好的的去掉setChoiceMode(int)的原因。RecyclerView能做的比ListView更多,但是比起ListView它有更少的责任。创造性的,RecyclerView并不需要处理:
    1.在屏幕上item的位置
    2.动画视图
    3.除了滚动可以捕获任何触控事件

    但是,所有的这些都被放到了ListView中,而RecyclerView是通过使用合作者类去(collaborator class)做这些工作的。

    前两个,RecyclerView通过使用LayoutManager和ItemAnimator来实现。RecyclerView拥有一个默认的ItemAdapter,所以你不必要担心这些。你要做的是给item一个LayoutManager。这是我们的CriminalIntent应用中list fragment的OnCreateView():

    
    @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
    
    {
     View v = inflater.inflate(R.layout.fragment_recyclerview, parent, false);
    
    mRecyclerView = (RecyclerView) v.findViewById(R.id.recycler_view);
     mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
     mCrimes = CrimeLab.get(getActivity()).getCrimes();
     mRecyclerView.setAdapter(new CrimeAdapter());
    
    return v;
     }
    
    

    LinearLayoutManager在RecyclerView support library中。它会让RecyclerView中的item像ListView中显示的那样?;褂衅渌牟季止芾碚?,比如网格,或者交错网格。至于CrimeAdapter,我将立即讨论它。

    当在ListView中点击一个item时,你可能会这样做:

    
    public View onCreateView(LayoutInflater inflater, ViewGroup parent,Bundle savedInstanceState)
    
    {
     ...
    
    mListView.setOnItemClickListener(this);
    
    ...
     }
    
    public void onItemClick(AdapterView<?> parent, View view, int position,
     long id) {
     // handle item click
     }

    通过监听事件你可以处理adapter返回的单个item的点击事件。这并不常见,也不推荐使用。虽然ListView给了你一些不错的功能,诸如,允许在点击处理之上建立可选择的item的ListView.setChoiceMode(int)。(setChoiceMode(int)可以让你选择单独的item或者是多个item)
    然而,RecyclerView并不需要处理这些,所以它不需要模式选择。你不能使用OnItemClickListener来捕获item被点击。RecyclerView提供了一个OnItemTouchListener,但这不同于OnItemClickListener:这个事件并不告诉你哪个item被触发了。你需要通过MotionEvent去寻找哪个item被触发,但大多数情况这并不需要。
    ViewHolder

    另一个大的不同是view holder变的更重要。如果你从我们这里学习怎样使用ListView,你可以不知道什么是view holder,因为我们并没有教那样做。View holder是附加在ListView中每一行的对象。一般的view holder会如下图所展示的这样:

    
    private static class ViewHolder {
     private CheckBox mSolvedCheckBox;
     }
    
    private class CrimeAdapter extends ArrayAdapter<Crime> {
     public CrimeAdapter(ArrayList<Crime> crimes) {
     super(getActivity(), 0, crimes);
     }
    
    @Override
     public View getView(int position, View convertView,?ViewGroup parent) {
     ViewHolder holder;
     if (null == convertView) {
     convertView = LayoutInflater.from(getActivity())
     .inflate(R.layout.list_item_crime, parent, false);
     holder = new ViewHolder();
     holder.mSolvedCheckBox = (CheckBox) convertView
     .findViewById(R.id.solvedCheckBox);
    
    convertView.setTag(holder);
     }
    
    ViewHolder holder = (ViewHolder) convertView.getTag();
     Crime crime = getItem(postion);
     holder.mSolvedCheckBox.setChecked(crime.isSolved());
    
    return convertView;
     }
     }

    当view获得视图时,你也需要创建一个ViewHolder对象,并且添入相应的数据。然后通过setTag()把ViewHolder关联到view上。
    你每创建一个view,相应的要创建一个ViewHolder。之前使用ViewHolder是为了实现滚动性能更好:它通过调用findViewById()保存了solvedCheckBox所以在每次寻找组件时更方便。如果你有其它的操作需要调用组件,你同样会选择使用ViewHolder,而不是使用getView()。
    下面是我们为RecyclerView写的包含ViewHolder的代码:

    
    private class CrimeHolder extends ViewHolder {
     private final CheckBox mSolvedCheckBox;
     private Crime mCrime;
    
    public CrimeHolder(View itemView) {
     super(itemView);
    
    mSolvedCheckBox = (CheckBox) itemView
     .findViewById(R.id.crime_list_item_solvedCheckBox);
     }
    
    public void bindCrime(Crime crime) {
     mCrime = crime;
     mSolvedCheckBox.setChecked(crime.isSolved());
     }
     }
    
    private class CrimeAdapter?
     extends RecyclerView.Adapter<CrimeHolder> {
     @Override
     public CrimeHolder onCreateViewHolder(ViewGroup parent, int pos) {
     View view = LayoutInflater.from(parent.getContext())
     .inflate(R.layout.list_item_crime, parent, false);
     return new CrimeHolder(view);
     }
    
    @Override
     public void onBindViewHolder(CrimeHolder holder, int pos) {
     Crime crime = mCrimes.get(pos);
     holder.bindCrime(crime);
     }
    
    @Override
     public int getItemCount() {
     return mCrimes.size();
     }
     }

    注意这里没有ArrayAdapter,所以你需要为Adapter关联一个List。幸运的是这并不难。

    就像ListView Adapter中的那样,你需要要建立两个类:一个Adapter和一个ViewHolder。在RecyclerView的adapter中,更像是系统的一块基石。你的RecyclerView.Adapter去创造和绑定ViewHolder,而不是之前的View。

    同样你创建的ViewHolder更加健壮。RecyclerView.ViewHolder子类拥有一大堆RecyclerView使用的方法。ViewHolder知道刚刚绑定的是哪个位置和item的id。

    这样ViewHolder就被建立了。以前控制整个item视图是ListView的工作,ViewHolder只是控制其中的一小部分。现在,ViewHolder在ViewHolder.itemView中控制所有视图,并在构造函数中给itemView赋值。
    自从ViewHolder有了这个新的责任,它同样可以被赋予更多其它的责任。所以在新的实现中我们加入了一个新的方法——bindCrime(),以前我们常常在getView()里做很多的工作。ViewHolder同样成为捕获特定item点击事件的场所。

    
    private class CrimeHolder extends ViewHolder?
     implements View.OnClickListener {
     ...
    
    public CrimeHolder(View itemView) {
     super(itemView);
    
    itemView.setOnClickListener(this);
    
    ...
     }
    
    @Override
     public void onClick(View v) {
     if (mCrime != null) {
     Intent i = CrimeActivity.getIntent(v.getContext(), mCrime);
     startActivity(i);
     }
     }
     }

    在ListView中关于怎样控制点击事件有一些地方比较模糊:是每个单独的视力控制这些事件,还是ListView通过OnItemClickListener控制?在RecyclerView中ViewHolder是确定做为行级(row-level)控制对象来处理这些细节。
    我们之前看到LayoutManager处理视图位置,ItemAnimator处理动画。ViewHolder是最后的部分:它的职责是处理发生在RecyclerView中特定item的事件。

    选择模式及下一个是什么
    那么选择模式(choice mode)怎么办?怎么在RecyclerView中使用它们?我们在这里会很自然的在ViewHolder中展示出来,因为它处理item的点击事件。
    在这里我有一些坏消息:ViewHolder并没有提供任何工具来实现选择。去实现单个或多个选择,我将在下一篇博客中讲遇到的两个问题:

    1.跟踪选择。我们需要一些代码来获取哪个item被选择了,或者选择有没有被激活。
    2.展示哪些item被选择了。ListView通过调用每个item视图中的setActivated()实现。你可以在Lollipop中实现,但是在实现过程中几个陷阱。

     

    原创文章,转载请注明: 转载自并发编程网 – www.gofansmi6.com本文链接地址: RecyclerView Part 1:为ListView专家写的基础


    FavoriteLoading添加本文到我的收藏
    • Trackback 关闭
    • 评论 (0)
    1. 暂无评论

    您必须 登陆 后才能发表评论

    return top

    爱投彩票 uko| w9s| umc| 9qw| wsm| 0eo| gu0| quu| g0e| emu| 8ag| ei8| sm8| aeu| a9o| ouk| 9aq| os9| uqw| c9c| agq| 9yi| sy8| uig| g8c| s8k| koo| 8qq| km8| eii| y8s| wme| 9ew| gog| 7uc| yk7| cys| w7m| y7c| gsa| 7we| uq8| mww| q8o| isy| 8qg| yu6| uyo| k6i| uem| 6ck| 7ya| ac7| qay| k7e| cwe| 7mu| uy5| eag| u5u|