【问题标题】:RecylcerView adapter with viewModel and Live data带有 viewModel 和 Livedata 的 RecyclerView 适配器
【发布时间】:2019-02-04 10:09:48
【问题描述】:

我开始使用 android jetpack arch 组件并且遇到了一些混乱。另请注意,数据绑定不是一种选择。

我有一个具有 RecyclerView 的活动。我有一个如下所示的 ViewModel

public class Movie extends ViewModel {


public Movie movie;
public URL logoURL;

private MutableLiveData<Drawable> logo;

public MutableLiveData<Drawable> getLogo() {

    if (logo == null) {
        logo = new MutableLiveData<>();
    }
    return logo;
}


public PikTvChannelItemVM(Movie movie, URL logo) {

    this.movie = movie;
    this.logoURL = logoURL;


}

public Bitmap getChannelLogo() {

  //Do some network call to get the bitmap logo from the url
 }

}

以上都很好,尽管在我的回收站视图中有以下代码。尽管在 onbindviewholder 中,当我尝试从视图模型实时数据中观察返回的图像时,它需要一个生命周期所有者引用,而我的回收站视图中没有该引用。请帮忙谢谢

public class MovieRecyclerViewAdapter extends RecyclerView
    .Adapter<MovieRecyclerViewAdapter.MovieItemViewHolder> {

public List<MovieViewModel> vmList;


public MovieRecyclerViewAdapter(List<MovieViewModel> vmList) {

    this.vmList = vmList;
    setHasStableIds(true);
}

@Override
public MovieItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    MovieView itemView = new MovieView(parent.getContext(), null);
    itemView.setLayoutParams(new ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
    ));
    return new MovieItemViewHolder(itemView);
}

@Override
public void onBindViewHolder(@NonNull MovieItemViewHolder holder, int position) {


    vmList.get(position).observe(?????, users -> {

  // As you can see I have no reference to the life cycle owner
       holder.imageView.setimage(some drawable returned by the View Model)
    });
}


@Override
public long getItemId(int position) {

    return position;
}

@Override
public int getItemViewType(int position) {

    return position;
}


@Override
public int getItemCount() {

    return vmList.size();
}

class MovieItemViewHolder extends RecyclerView.ViewHolder {

    private MovieView channelView;

    public MovieItemViewHolder(View v) {

        super(v);
        channelView = (MovieView) v;
    }

    public MovieView getChannelView() {

        return channelView;
    }
 }

}

【问题讨论】:

    标签: java android mvvm android-recyclerview


    【解决方案1】:

    我会尝试向适配器发送一个列表以显示它。我会在适配器之外观察数据,因为观察数据不是适配器的责任,而是显示它。

    【讨论】:

      【解决方案2】:

      您的适配器列表类型不应是视图模型。如果您想在没有绑定的情况下使用实时数据,您希望在列表更新时自动更改用户界面。

      你可以这样做:

      首先,您的电影类必须是模型类,而不是视图模型。

      像往常一样做适配器。只需添加一个setList(Movie) 方法。此方法应更新适配器列表。更新列表后不要忘记通知适配器。

      然后像

      那样创建livedata列表
      MutableLiveData<List<Movie>> movieLiveData = 
          new MutableLiveData<>();
      

      你想要的地方。

      在活动中观察这个列表并在观察{}中调用适配器setList(Movie)方法。

      如果你的列表更新了,setList(Movie) medhod 将被触发,然后你的 ui 将被更新。

      【讨论】:

        【解决方案3】:

        你可以这样做:

        视图模型:

        class MyViewModel : ViewModel() {
            private val items = MutableLiveData<List<String>>()
        
            init {
                obtainList()
            }
        
            fun obtainList() { // obtain list from repository
                items.value = listOf("item1", "item2", "item3", "item4")
            }
        
            fun getItems(): LiveData<List<String>> {
                return items
            }
        }
        

        您的片段(或活动):

        public class ContentFragment extends Fragment {
            private MyViewModel viewModel;
            private RecyclerView recyclerView;
            private MyAdapter adapter;
            
            @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                viewModel = new ViewModelProvider(this).get(MyViewModel.class);
            }
        
            @Override
            public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, 
                    Bundle savedInstanceState) {
                View root = inflater.inflate(R.layout.fragment_main, container, false);
                recyclerView = root.findViewById(R.id.recycler_view);
                recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 4));
               
                // add observer 
                viewModel.getItems().observe(this, items -> {
                    adapter = new MyAdapter(items); // add items to adapter
                    recyclerView.setAdapter(adapter);
                });
        
                return root;
            }
        

        适配器:

        class MyAdapter(val list: List<String>) : RecyclerView.Adapter<MyAdapter.TextViewHolder {
            ...
            override fun onBindViewHolder(holder: TextViewHolder, position: Int) {
                holder.textView.text = list[position] // assign titles from the list.
                ...
            }
        }
        

        可以使用任何自定义对象来代替字符串对象。

        【讨论】:

          猜你喜欢
          • 2018-12-23
          • 2019-07-17
          • 2022-01-18
          • 2016-01-29
          • 1970-01-01
          • 1970-01-01
          • 2020-10-23
          • 2019-10-10
          • 2017-03-28
          相关资源
          最近更新 更多