Я изучаю новые компоненты и пытаюсь использовать LiveData с DataBinding и ModelView.У меня проблема с отображением элементов в программе RecycleView (обновление пользовательского интерфейса).Вот мой ModelView:
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();
}
}
Итак, он не падает, только утилита пуста.Если вам нужны дополнительные объяснения, просто спросите.Буду признателен за любую помощь.Thanx