【问题标题】:LiveData with ModelView not updating adapter带有 ModelView 的 LiveData 不更新适配器
【发布时间】:2018-05-23 10:24:22
【问题描述】:

我正在学习新组件并尝试将 LiveData 与 DataBinding 和 ModelView 一起使用。我在 recyclerview 上显示项目时遇到问题(更新 UI)。这是我的模型视图:

 

public class PlacesViewModel extends ViewModel {

private MutableLiveData<List<Place>> placeList;
private Repository repository;


public PlacesViewModel() {
    repository = Repository.getInstance();
}

public LiveData<List<Place>> getPlaceList() {
    if (placeList == null) {
        placeList = new MutableLiveData<List<Place>>();
        getPlaces();
    }
    return placeList;
}

private void getPlaces() {
    repository.getLocationsFromBackend(new DataSource.GetLocationsCallback() {
        @Override
        public void onSuccess(MutableLiveData<List<Place>> body) {
            if (body != null) {
                placeList = body;
            } else {
                placeList = new MutableLiveData<>();
            }
        }

        @Override
        public void onError(int code) {

        }

        @Override
        public void onUnknownError() {

        }

        @Override
        public void onNoInternet() {

        }

        @Override
        public void onNoServer() {

        }

        @Override
        public void onAlreadyPairedError() {

        }

        @Override
        public void onNoCustomerError() {

        }

        @Override
        public void onLoadIndicator(boolean active) {

        }

        @Override
        public void reAuthenticate() {

        }
    });
}

问题来了,当我启动应用程序时,屏幕是“空的”。但是,当我处于调试模式并在 getPlaceList() 行中时,我可以切换到后台线程以使用改造来执行 api 调用。只有它起作用了......

这是我的存储库单例方法:

public class Repository implements DataSource {

private static Repository INSTANCE;
private ApiService service = new RetrofitFactory().getService();
private static final int RESPONSE_OK = 0;
private final MutableLiveData<List<Place>> data = new MutableLiveData<>();


public synchronized static Repository getInstance() {
    if (INSTANCE==null) {
        INSTANCE=new Repository();
    }
    return(INSTANCE);
}

private Repository() {
}

private <T extends BaseResponse> void handleActualResult(BaseLoadCallback<T> dataSource,
                                                         MutableLiveData<List<Place>> actualResult) {
    final int resultCode = 0;
    switch (resultCode) {
        case RESPONSE_OK:
            dataSource.onSuccess(actualResult);
            break;
        default:
            dataSource.onError(resultCode);
            break;
    }
}

@Override
public void getLocationsFromBackend(GetLocationsCallback presener) {
    final SecurityRequest request = new SecurityRequest();
    service.getPlaces(request).enqueue(new Callback<GetPlacesResponse>() {
        @Override
        public void onResponse(@NonNull Call<GetPlacesResponse> call, @NonNull Response<GetPlacesResponse> response) {
            if (response.isSuccessful()) {
                if (response.body() != null) {
                    data.postValue(response.body().getLokali());
                    handleActualResult(presener, data);
                }
            }
        }
        @Override
        public void onFailure(@NonNull Call<GetPlacesResponse> call, @NonNull Throwable t) {
            Log.d("Error: ", t.getMessage());
        }
    });
}

@Override
public List<Place> getLocations() {
    return null;
}

}

它转到 onResposne 然后返回 getPlaceList() 并返回填充的对象列表。以下是我如何创建 viewmodel 实例并观察 LiveData 对象:

public class LocationFragment extends Fragment {

private PlacesViewModel placesViewModel;
private RecyclerView recyclerView;
private PlaceCustomAdapter customAdapter;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    recyclerView = view.findViewById(R.id.recyclerViewId);
    placesViewModel = ViewModelProviders.of(LocationFragment.this).get(PlacesViewModel.class);

    customAdapter = new PlaceCustomAdapter(getLayoutInflater());

    recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
    recyclerView.setHasFixedSize(false);

    placesViewModel.getPlaceList().observe(this, places -> {
        customAdapter.setList(places);
        recyclerView.setAdapter(customAdapter);
    });
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    return(inflater.inflate(R.layout.activity_main, container, false));
}

这也是我的适配器:

public class PlaceCustomAdapter extends RecyclerView.Adapter<PlaceCustomAdapter.CustomLocationViewHolder> {

private LayoutInflater layoutInflater;
private List<Place> placeList;

public PlaceCustomAdapter(LayoutInflater layoutInflater) {
    this.layoutInflater = layoutInflater;
}

@NonNull
@Override
public PlaceCustomAdapter.CustomLocationViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    ViewDataBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.single_item_row_recycler_view, parent, false);
    return new PlaceCustomAdapter.CustomLocationViewHolder(binding);
}

@Override
public void onBindViewHolder(@NonNull PlaceCustomAdapter.CustomLocationViewHolder holder, int position) {
    Place p = placeList.get(position);
    holder.bind(p);
}

void setList(List<Place> placeList) {
    this.placeList = placeList;
    notifyDataSetChanged();
}

@Override
public int getItemCount() {
    return(placeList == null ? 0 : placeList.size());
}

public class CustomLocationViewHolder extends RecyclerView.ViewHolder {

    private final ViewDataBinding binding;

    public CustomLocationViewHolder(ViewDataBinding binding) {
        super(binding.getRoot());
        this.binding = binding;
    }

    public void bind(Object obj) {
        binding.setVariable(BR.model, obj);
        binding.executePendingBindings();
    }
}

所以,它不会崩溃,只有 recycler 是空的...如果您需要任何额外的解释,请问。 我将不胜感激任何帮助。谢谢

【问题讨论】:

    标签: java android mvvm android-databinding android-livedata


    【解决方案1】:

    我刚刚发现出了什么问题。我正在调用一个方法 handleActualResult(presener, data); 在错误的地方。相反,在 onSuccess 中,我将其用于处理响应...

      @Override
    public void getLocationsFromBackend(GetLocationsCallback presener) {
        final SecurityRequest request = new SecurityRequest();
        service.getPlaces(request).enqueue(new Callback<GetPlacesResponse>() {
            @Override
            public void onResponse(@NonNull Call<GetPlacesResponse> call, @NonNull Response<GetPlacesResponse> response) {
                if (response.isSuccessful()) {
                    if (response != null) {
                        data.postValue(response.body().getLokali());
                    } else {
                        data = new MutableLiveData<>();
                    }
                }
            }
            @Override
            public void onFailure(@NonNull Call<GetPlacesResponse> call, @NonNull Throwable t) {
                Log.d("Error: ", t.getMessage());
            }
        });
        handleActualResult(presener, data);
    }
    

    如果有人反对同样的问题...享受吧!

    【讨论】:

      猜你喜欢
      • 2019-02-04
      • 2020-10-23
      • 2021-11-15
      • 2019-01-08
      • 1970-01-01
      • 2019-06-21
      • 1970-01-01
      • 1970-01-01
      • 2019-07-17
      相关资源
      最近更新 更多