【问题标题】:Reuse a inflated view, without inflating more than once重复使用膨胀的视图,而不是多次膨胀
【发布时间】:2017-01-08 05:04:02
【问题描述】:

我想重用一个膨胀的视图,就像 listView 适配器对 convertView 所做的那样。我一直潜伏在适配器的源代码上,没有运气。

我需要根据数据向 recyclerItemView 添加动态视图,现在我根据需要添加视图的次数,但考虑到它在 recyclerView 中,此操作可能会变得非常昂贵,具体取决于数据量和滚动用户的行为。

我的问题的其他解决方案是在 recyclerItem 内创建一个列表视图,因此列表视图不能滚动,根据动态添加的数据展开到最大高度(使列表视图容器展开以显示其所有数据)并使recyclerItem 根据其高度展开。

活动

public class Main1Activity extends AppCompatActivity {

    RecyclerView recyclerView;
    CustomAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main1);
        recyclerView = (RecyclerView) findViewById(R.id.recycler);
        setUpRecycler();
    }

    private void setUpRecycler(){
        Sample sample1 = new Sample("List of Items1");
        Sample sample2 = new Sample("List of Items2");
        Sample sample3 = new Sample("List of Items3");
        List<Sample> sampleList = new ArrayList<>();
        sampleList.add(sample1);
        sampleList.add(sample2);
        sampleList.add(sample3);

        adapter = new CustomAdapter(this,sampleList);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
    }
}

<?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="match_parent"
    android:padding="30dp">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v7.widget.RecyclerView>

</RelativeLayout>

型号

public class Sample {

    String name;

    public Sample(){}

    public Sample(String name) {
         this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

XML 项目

**item_list**

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="40dp">

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

</LinearLayout>

**item_smaple**

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

<TextView
    android:id="@+id/name"
    android:layout_width="120dp"
    android:layout_height="40dp"
    android:layout_margin="10dp"
    android:text="List of Items"
    android:textSize="20sp"/>

<LinearLayout
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="30dp"
    android:orientation="vertical"/>

</LinearLayout>

适配器

public class CustomAdapter extends   RecyclerView.Adapter<CustomAdapter.ViewHolder> {

private List<Sample> mySamples;
private Context mContext;

public CustomAdapter(Context context, List<Sample> mySamples) {
    this.mContext = context;
    this.mySamples = mySamples;
}

private Context getContext() {
    return mContext;
}

public static class ViewHolder extends RecyclerView.ViewHolder {

    public TextView name;
    public LinearLayout linearLayout;

    public ViewHolder(View itemView) {
        super(itemView);
        name = (TextView) itemView.findViewById(R.id.name);
        linearLayout = (LinearLayout) itemView.findViewById(R.id.linearLayout);
    }
}

@Override
public CustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    Context context = parent.getContext();
    LayoutInflater inflater = LayoutInflater.from(context);
    View contactView = inflater.inflate(R.layout.item_sample, parent, false);
    ViewHolder viewHolder = new ViewHolder(contactView);
    return viewHolder;
}

@Override
public void onBindViewHolder(CustomAdapter.ViewHolder holder, int position) {
    Sample sample = mySamples.get(position);

    holder.name.setText(sample.getName());

    LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v = inflater.inflate(R.layout.item_list, null, false);
    for (int i = 0; i < 20; i++){
        TextView textView = (TextView) v.findViewById(R.id.textView);
        textView.setText("hello"+i);
        holder.linearLayout.addView(v);
    }
}

@Override
public int getItemCount() {
    return mySamples.size();
}
}

现在我正在循环内充气。如何修改视图参数以使其可重用于框架?

我的应用在 addView() 上崩溃 -->java.lang.IllegalStateException: 指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()。

【问题讨论】:

  • 那么使用 RecyclerView 有什么问题?
  • 我的问题是我想膨胀一个复杂的布局并用 addView() 将它添加到线性布局中,所以如果 recycler-item 需要在线性布局内膨胀 4-5 这个布局,这可能会减慢甚至冻结 recyclerview 上的滚动;因为膨胀操作将在回收器项填充和清空视图时执行大量次,并且膨胀它是一个成本高昂的操作,如果可能的话,列表小部件会避免重复。现在我会很容易地在每个回收站做 2-3 次。
  • 是的,膨胀视图是一项昂贵的操作,这就是他们制作 ListView/RecyclerView 的原因,这样它就不会每次都膨胀视图,但它会重用它们并绑定数据
  • 如果你读了第三个段落,你可以看到我已经考虑过了,但是我调查了一个列表视图,它的行为就像我需要但没有运气,所以我想自己膨胀视图,如果你知道如何创建我需要的列表视图(3 段)只需创建一个答案,这样我就可以检查它是否正确,谢谢您的时间:)

标签: android performance android-layout listview android-inflate


【解决方案1】:

您所指的问题是通过创建 RecyclerView 解决的问题,这是对 ListView 的升级。 RecyclerView 所做的是它会创建/膨胀说 5-10 个列表项,并且当用户开始滚动新的 listItem 视图时,实际上不会膨胀,实际上只是更新了 listItem 内的数据。

这是一个很好的解释器视频,说明了回收器视图实际上如何与一些代码一起工作。 https://www.youtube.com/watch?v=Wq2o4EbM74k

我希望这能消除您对通货膨胀问题的疑虑。

【讨论】:

    【解决方案2】:

    我的应用在 addView() 上崩溃 -->java.lang.IllegalStateException: The specified child has a parent.您必须先在孩子的父母上调用 removeView()。

    尝试:

    @Override
    public void onBindViewHolder(CustomAdapter.ViewHolder holder, int position) {
        Sample sample = mySamples.get(position);
    
        holder.name.setText(sample.getName());
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context
                .LAYOUT_INFLATER_SERVICE);
    
        for (int i = 0; i < 20; i++) {
            View v = inflater.inflate(R.layout.item_list, holder.linearLayout, false);
            TextView textView = (TextView) v.findViewById(R.id.textView);
            textView.setText("hello" + i);
            holder.linearLayout.addView(v);
        }
    }
    

    itemSample.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical">
    
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:layout_margin="10dp"
        android:text="List of Items"
        android:textSize="20sp"/>
    
    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_marginLeft="30dp"
        android:orientation="vertical"
        android:isScrollContainer="true"
        />
    
    </LinearLayout>
    

    itemList.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="40dp"
      android:isScrollContainer="true"
      android:id="@+id/txt_cont"
      >
    
     <TextView
      android:id="@+id/textView"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"/>
    </LinearLayout>
    

    You should try answer @

    【讨论】:

    • 我想要的代码是对所有视图只执行一次充气操作,如果您阅读我的问题上的 cmets,您会看到我讨论了您在此处发布的代码可能是,感谢您抽出宝贵时间,但这不是我要找的。(确实,我的代码与您发布的代码完全相同,直到我弄清楚为止:P)
    猜你喜欢
    • 1970-01-01
    • 2016-09-29
    • 2018-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多