数据绑定recyclerview适配器从livedata接收到空列表 [英] databinding recyclerview adapter received null list from livedata

查看:86
本文介绍了数据绑定recyclerview适配器从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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆