实际上,在使用Java中的RecyclerView中,AsyncLayoutInflator几乎没有什么资源可用。我实际上不得不使用少量可用于internet上的Kotlin资源,编写了自己版本的@Artem答案的Java代码。
首先,我们为recyclerview使用一个简单的虚拟视图,以便recycleview快速加载,并在后台使用asyncLayoutInflator将其余复杂的视图添加到simpleview中。
onBindExecutes之所以执行迅速且无法访问复杂布局的原因是onCreate方法仅创建了虚拟视图,因此当您尝试访问复杂视图时,它会返回空异常,因为复杂视图尚未生成。为了克服这一点,我们将列表传递给正在生成复杂视图的类,并相应地更新视图。
以下是如何实施它的程序。我的代码可能有点凌乱,因为我仍在学习,并且可以进一步改进。
MyListData.Java
public class MyListData{
private String description;
private int imgId;
public MyListData(String description, int imgId) {
this.description = description;
this.imgId = imgId;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getImgId() {
return imgId;
}
public void setImgId(int imgId) {
this.imgId = imgId;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyListData[] myListData = new MyListData[] {
new MyListData("Email", android.R.drawable.ic_dialog_email),
new MyListData("Info", android.R.drawable.ic_dialog_info),
new MyListData("Delete", android.R.drawable.ic_delete),
new MyListData("Dialer", android.R.drawable.ic_dialog_dialer),
new MyListData("Alert", android.R.drawable.ic_dialog_alert),
new MyListData("Map", android.R.drawable.ic_dialog_map),
new MyListData("Email", android.R.drawable.ic_dialog_email),
new MyListData("Info", android.R.drawable.ic_dialog_info),
new MyListData("Delete", android.R.drawable.ic_delete),
new MyListData("Dialer", android.R.drawable.ic_dialog_dialer),
new MyListData("Alert", android.R.drawable.ic_dialog_alert),
new MyListData("Map", android.R.drawable.ic_dialog_map),
};
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
MyListAdapter adapter = new MyListAdapter(myListData);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
}
}
MyListAdapter
public class MyListAdapter extends ListAdapter<RecyclerView.ViewHolder> {
private MyListData[] listdata;
public MyListAdapter(MyListData[] listdata) {
this.listdata = listdata;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
DummyView dummyView= new DummyView(parent.getContext());
dummyView.inflate();
return new viewHolder(dummyView);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
setupDummyView(holder, position);
}
}
private void setupDummyView(RecyclerView.ViewHolder holder, int position) {
DummyView items = (DummyView) holder.itemView;
items.bindWhenInflated(items.textView, listdata[position]); - - - -> bindWhenInflated is a method in DummyViewClass which extends AsyncLayoutClass
}
@Override
public int getItemCount() {
return return listdata.length;
}
static class ListViewHolder extends RecyclerView.ViewHolder {
public ListViewHolder(ViewGroup view) {
super(view);
}
}
private static final class DummyView extends AsyncLayout {
public Context context;
MaterialTextView textView;
private final int layoutId = R.layout.datacolumn;
public DummyView(@NonNull Context context) {
super(context);
this.context = context;
}
public int getLayoutId() {
return this.layoutId;
}
@Override
public View getView(View view) {
textView = view.findViewById(R.id.dataText);
return super.getView(view);
}
public MaterialTextView getTextView() {
return textView;
}
}
}
异步布局
public class AsyncLayout extends FrameLayout {
private final int layoutId;
private boolean isInflated = false;
private Context context;
private final List<MyListData>bindingfunction;
public AsyncLayout(Context context) {
super(context);
this.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
this.context = context;
layoutId = -1;
bindingfunction = new ArrayList<>();
}
public int getLayoutId() {
return layoutId;
}
public final void inflate() {
AsyncLayoutInflater asyncInflator = new AsyncLayoutInflater(context);
asyncInflator.inflate(this.getLayoutId(),this, (view, resid, parent) -> {
isInflated = true;
assert parent != null;
parent.addView(getView(view));
});
}
public View getView(View view) {
MaterialTextView textView = view.findViewById(R.id.listText);
for (MyListData data :bindingfunction
) {
textView.setText(data.getDescription());
}
return view;
}
public void bindWhenInflated(MaterialTextView textView, MyListData listData) {
if(isInflated){
textView.setText(listdata.getDescription());
}else{
bindingfunction.add(listData);
}
}
}
我想总结说,AsyncLayoutInflator 应该只在有限的情况下使用,因为其不正确的实现可能会导致意外的 UI 行为。