数据绑定recyclerview适配器从livedata接收到空列表 [英] databinding recyclerview adapter received null list from livedata
问题描述
我想向recyclerview提供元素和livedata的列表.我使用了数据绑定适配器,当我想将数据发送到适配器时,列表从livedata返回null.整个代码如下.谢谢
I want to feed the recyclerview with a list of elements and livedata. I used data binding adapter and when I want to send data to adapter the list return null from livedata. the whole code are below. thanks
我调试了代码,我看到数据何时从AppDbHelper.java到HomeViewmodel.java并将绑定适配器设置为实时数据.因此,尽管livedata不为null,但数据绑定适配器(heartRateResultsModels)处的arraylist为null,导致应用程序崩溃.
I debugged the code and I saw when the data came from the AppDbHelper.java to HomeViewmodel.java and set to the live data the bindingadapter didn't change. thus, although the livedata is not null, the arraylist at databinding adapter(heartRateResultsModels) is null and made the app crashed.
1.fragment_home.xml
1.fragment_home.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="ir.basamadazmanovin.heartrate.ui.main.home.HomeViewModel" />
</data>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:refreshing="@{viewModel.isLoading}">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.home.HomeFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/fragment_home_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:adapter="@{viewModel.heartRateResultsLiveData}"
tools:listitem="@layout/row_fragment_home" />
</FrameLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</layout>
2.BaseFragment.java
2.BaseFragment.java
public abstract class BaseFragment<T extends ViewDataBinding, V extends BaseViewModel> extends Fragment {
protected FragmentNavigation mFragmentNavigation;
private BaseActivity mActivity;
private View mRootView;
private T mViewDataBinding;
private V mViewModel;
public abstract int getBindingVariable();
public abstract
@LayoutRes
int getLayoutId();
public abstract V getViewModel();
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof BaseActivity) {
BaseActivity activity = (BaseActivity) context;
this.mActivity = activity;
activity.onFragmentAttached();
}
if (context instanceof FragmentNavigation) {
mFragmentNavigation = (FragmentNavigation) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
performDependencyInjection();
super.onCreate(savedInstanceState);
mViewModel = getViewModel();
setHasOptionsMenu(false);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mViewDataBinding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
mRootView = mViewDataBinding.getRoot();
return mRootView;
}
public BaseActivity getBaseActivity() {
return mActivity;
}
public T getViewDataBinding() {
return mViewDataBinding;
}
public void hideKeyboard() {
if (mActivity != null) {
mActivity.hideKeyboard();
}
}
public boolean isNetworkConnected() {
return mActivity != null && mActivity.isNetworkConnected();
}
public void openActivityOnTokenExpire() {
if (mActivity != null) {
mActivity.openActivityOnTokenExpire();
}
}
private void performDependencyInjection() {
AndroidSupportInjection.inject(this);
}
public interface Callback {
void onFragmentAttached();
void onFragmentDetached(String tag);
}
}
3.HomeFragment.java
3.HomeFragment.java
public class HomeFragment extends BaseFragment<FragmentHomeBinding,HomeViewModel> implements HomeNavigator {
FragmentHomeBinding mFragmentHomeBinding;
@Inject
LinearLayoutManager mLayoutManager;
@Inject
HeartRateResultsAdapter mAdapter;
@Inject
ViewModelProviderFactory factory;
private HomeViewModel mHomeViewModel;
public static HomeFragment newInstance() {
return new HomeFragment();
}
@Override
public int getBindingVariable() {
return BR.viewModel;
}
@Override
public int getLayoutId() {
return R.layout.fragment_home;
}
@Override
public HomeViewModel getViewModel() {
mHomeViewModel = ViewModelProviders.of(this, factory).get(HomeViewModel.class);
return null;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHomeViewModel.setNavigator(this);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mFragmentHomeBinding = getViewDataBinding();
setUp();
}
private void setUp() {
mLayoutManager.setOrientation(RecyclerView.VERTICAL);
mFragmentHomeBinding.fragmentHomeRecyclerView.setLayoutManager(mLayoutManager);
mFragmentHomeBinding.fragmentHomeRecyclerView.setItemAnimator(new DefaultItemAnimator());
mFragmentHomeBinding.fragmentHomeRecyclerView.setAdapter(mAdapter);
}
@Override
public void handleError(Throwable throwable) {
}
}
4.BaseViewModel.java
4.BaseViewModel.java
public class BaseViewModel<N> extends ViewModel {
private final DataManager mDataManager;
private final ObservableBoolean mIsLoading = new ObservableBoolean(false);
private final SchedulerProvider mSchedulerProvider;
private CompositeDisposable mCompositeDisposable;
private WeakReference<N> mNavigator;
public BaseViewModel(DataManager dataManager,
SchedulerProvider schedulerProvider) {
this.mDataManager = dataManager;
this.mSchedulerProvider = schedulerProvider;
this.mCompositeDisposable = new CompositeDisposable();
}
@Override
protected void onCleared() {
mCompositeDisposable.dispose();
super.onCleared();
}
public CompositeDisposable getCompositeDisposable() {
return mCompositeDisposable;
}
public DataManager getDataManager() {
return mDataManager;
}
public ObservableBoolean getIsLoading() {
return mIsLoading;
}
public void setIsLoading(boolean isLoading) {
mIsLoading.set(isLoading);
}
public N getNavigator() {
return mNavigator.get();
}
public void setNavigator(N navigator) {
this.mNavigator = new WeakReference<>(navigator);
}
public SchedulerProvider getSchedulerProvider() {
return mSchedulerProvider;
}
}
5.HomeViewModel.java
5.HomeViewModel.java
public class HomeViewModel extends BaseViewModel<HomeNavigator> {
private MutableLiveData<ArrayList<HeartRateResultsModel>> heartRateResultsLiveData;
public HomeViewModel(DataManager dataManager, SchedulerProvider schedulerProvider) {
super(dataManager, schedulerProvider);
heartRateResultsLiveData = new MutableLiveData<>();
fetchRepos();
}
public void fetchRepos() {
setIsLoading(true);
getCompositeDisposable().add(getDataManager()
.getHeartRateResults()
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(heartRateResultsModels -> {
heartRateResultsLiveData.setValue(heartRateResultsModels);
setIsLoading(false);
}, throwable -> {
setIsLoading(false);
getNavigator().handleError(throwable);
}));
}
public LiveData<ArrayList<HeartRateResultsModel>> getHeartRateResultsLiveData() {
return heartRateResultsLiveData;
}
}
6.BindingUtils.java
6.BindingUtils.java
public final class BindingUtils {
private BindingUtils() {
// This class is not publicly instantiable
}
@BindingAdapter("imageUrl")
public static void setImageUrl(ImageView imageView, String url) {
Context context = imageView.getContext();
Glide.with(context).load(url).into(imageView);
}
@BindingAdapter("onNavigationItemSelected")
public static void setOnNavigationItemSelectedListener(
BottomNavigationView view, OnNavigationItemSelectedListener listener) {
view.setOnNavigationItemSelectedListener(listener);
}
@BindingAdapter({"adapter"})
public static void addHeartRateResultsItems(RecyclerView recyclerView,
ArrayList<HeartRateResultsModel> heartRateResultsModels) {
HeartRateResultsAdapter adapter = (HeartRateResultsAdapter) recyclerView.getAdapter();
if (adapter != null) {
adapter.clearItems();
adapter.addItems(heartRateResultsModels);
}
}
}
7.DataManager.java
7.DataManager.java
public interface DataManager extends DbHelper, PreferencesHelper, ApiHelper {
}
8.DbHelper.java
8.DbHelper.java
public interface DbHelper {
Single<ArrayList<HeartRateResultsModel>> getHeartRateResults();
}
9.AppDataManager.java
9.AppDataManager.java
public class AppDataManager implements DataManager{
private final ApiHelper mApiHelper;
private final Context mContext;
private final DbHelper mDbHelper;
private final Gson mGson;
private final PreferencesHelper mPreferencesHelper;
@Inject
public AppDataManager(Context context,
DbHelper dbHelper,
PreferencesHelper preferencesHelper,
ApiHelper apiHelper,
Gson gson) {
mContext = context;
mDbHelper = dbHelper;
mPreferencesHelper = preferencesHelper;
mApiHelper = apiHelper;
mGson = gson;
}
@Override
public Single<ArrayList<HeartRateResultsModel>> getHeartRateResults() {
return mDbHelper.getHeartRateResults();
}
}
10.AppDbHelper.java
10.AppDbHelper.java
@Singleton
public class AppDbHelper implements DbHelper{
private final AppDatabase mAppDatabase;
@Inject
public AppDbHelper(AppDatabase appDatabase) {
this.mAppDatabase = appDatabase;
}
@Override
public Single<ArrayList<HeartRateResultsModel>> getHeartRateResults() {
return Single.fromCallable(new Callable<ArrayList<HeartRateResultsModel>>() {
@Override
public ArrayList<HeartRateResultsModel> call() throws Exception {
ArrayList<HeartRateResultsModel> models = new ArrayList<>();
models.add(new HeartRateResultsModel("","1"));
models.add(new HeartRateResultsModel("","2"));
return models;
}
});
}
}
推荐答案
我在设置上不见了
mViewDataBinding.vm = viewModel
mViewDataBinding.vm = viewModel
其中"vm"是布局中的变量,"viewModel"是活动或片段中的局部变量
where "vm" is the variable in layout and "viewModel" is the local variable in activity or fragment
此外,正如@Menma建议的那样,不要忘记添加
Furthermore, as @Menma suggested, don't forget to add
mViewDataBinding.setLifecycleOwner(this);
mViewDataBinding.setLifecycleOwner(this);
这篇关于数据绑定recyclerview适配器从livedata接收到空列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!