簡體   English   中英

帶有 viewModel 和實時數據的 RecyclerView 適配器

[英]RecylcerView adapter with viewModel and Live data

我開始使用 android jetpack arch 組件並遇到了一些困惑。 另請注意數據綁定不是一個選項。

我有一個具有 RecylcerView 的活動。 我有一個如下所示的 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 中,當我嘗試從 viewmodels 實時數據中觀察返回的圖像時,它需要一個生命周期所有者引用,而我的回收器視圖中沒有。 請幫忙謝謝

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;
    }
 }

}

我會嘗試向適配器發送一個列表以顯示它。 我會觀察適配器外部的數據,因為觀察數據而不是顯示數據不是適配器的責任。

您的適配器列表類型不應是視圖模型。 如果您想在沒有綁定的情況下使用實時數據,您需要在列表更新時自動更改 ui。

你可以這樣做:

首先,您的電影類必須是模型類,而不是視圖模型。

像往常一樣做適配器。 只需添加一個setList(Movie)方法。 此方法應更新適配器列表。 不要忘記在更新列表后通知適配器。

然后創建 livedata 列表,如

MutableLiveData<List<Movie>> movieLiveData = 
    new MutableLiveData<>();

你想在哪里。

在 Activity 中觀察這個列表並在observe{} 中調用適配器 setList(Movie) 方法。

畢竟,如果您的列表更新了, setList(Movie) medhod 將被觸發,然后您的 ui 將被更新。

你可以這樣做:

視圖模型:

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.
        ...
    }
}

可以使用任何自定義對象代替 String 對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM