重复使用已充气的视图,无需多次充气

3
我希望能像ListView适配器一样重复使用已经膨胀的视图,但是我在适配器的源代码中没有找到相关内容。
我需要根据数据动态添加视图到RecyclerItemView中,现在我每次需要视图时都会膨胀(inflate)它,但要考虑到它是在RecyclerView中,这个操作可能会因为数据量和用户滚动行为而变得非常昂贵。
解决我的问题的另一个方法是在RecyclerItem内部创建一个ListView,使得ListView不可滚动,根据动态添加的数据自动扩展到最大高度(使ListView容器扩展以显示其所有数据),并根据其高度扩展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有什么问题呢? - lelloman
我的问题是,我想要填充一个复杂的布局并使用addView()添加到LinearLayout中,所以如果Recycler项需要在LinearLayout内填充4-5个此布局,则可能会减慢甚至冻结RecyclerView的滚动;因为填充操作将随着Recycler项的填充和清空视图而执行大量次数,并且填充是一项昂贵的操作,列表小部件尽可能避免重复。现在,每个Recycler行将轻松执行2-3次这样的操作。 - marcos E.
是的,填充视图是一项昂贵的操作,这就是为什么他们制作了ListView/RecyclerView,以便它不会每次都填充视图,而是重用它们并绑定数据。 - lelloman
如果您阅读第三段,您会发现我已经考虑过这个问题了,但是我调查了一下,没有找到像我需要的那样的列表视图,所以我想自己填充视图。如果您知道如何创建一个像我需要的列表视图(第三段),请回答,这样我就可以将其标记为正确答案,感谢您的时间 :) - marcos E.
2个回答

0
您所提到的问题是通过创建RecyclerView来解决的,它是ListView的升级版。 RecyclerView的作用是在创建/填充5-10个列表项时,当用户开始滚动时,不会再填充新的列表项视图,而是仅更新其中的数据。

这是一个非常好的说明视频,展示了如何使用代码来实现Recycler View。https://www.youtube.com/watch?v=Wq2o4EbM74k

希望这能够解决您对填充问题的疑虑。


0
我的应用程序在addView()上崩溃-->java.lang.IllegalStateException:指定的子项已经有一个父项。您必须先调用子项的父项上的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>

Just Raw Solution

你应该尝试回答 @


我需要的代码是仅对所有视图执行一次膨胀操作,如果您阅读了我的问题评论,您会看到我讨论了您发布的代码可能有多糟糕的性能,感谢您的时间,但这不是我要找的。(事实上,直到我想出了办法,我的代码才像您发布的代码一样正常工作:P) - marcos E.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接