0
votes

l'adaptateur de recyclage de liaison de données a reçu une liste nulle de livingata

Je souhaite alimenter la vue de recyclage avec une liste d'éléments et de données. J'ai utilisé un adaptateur de liaison de données et lorsque je veux envoyer des données à l'adaptateur, la liste renvoie null de livingata. le code entier est ci-dessous. merci

​​J'ai débogué le code et j'ai vu quand les données sont venues de AppDbHelper.java vers HomeViewmodel.java et définies sur les données en direct, l'adaptateur de liaison n'a pas changé. ainsi, bien que la valeur de vie ne soit pas nulle, l'arraylist de l'adaptateur de liaison de données (heartRateResultsModels) est null et l'application a planté.

1.fragment_home.xml

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

2.BaseFragment.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();
    }


}

3.HomeFragment .java

public interface DbHelper {
    Single<ArrayList<HeartRateResultsModel>> getHeartRateResults();

}

4.BaseViewModel.java

public interface DataManager extends DbHelper, PreferencesHelper, ApiHelper {

}

5.HomeViewModel.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);
        }
    }
}

6.BindingUtils.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;
    }
}

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

8.DbHelper .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) {

    }
}

9.AppDataManager.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);
    }
}

10.AppDbHelper.java

<?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>


0 commentaires

3 Réponses :


0
votes

ajoutez mViewDataBinding.setLifecycleOwner (this); sur la méthode: onViewCreated () à la classe BaseFragment , comme ceci:

@Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mViewDataBinding.setVariable(getBindingVariable(), mViewModel);
        mViewDataBinding.setLifecycleOwner(this);
        mViewDataBinding.executePendingBindings();
    }


0 commentaires

0
votes

1 . Assurez-vous toujours de définir vos variables de liaison XML dans votre contrôleur d'interface utilisateur (fragment ou activité)

Dans votre mise en page XML

bindingObj.setLifeCycleOwner = this

Dans votre contrôleur d'interface utilisateur (Fragment dans ce cas)

listViewModel = ViewModel(this).get(ListViewModel::class)
bindingObj.viewModel = listViewModel

2 . Il est nécessaire que vous définissiez setLifecycleOwner () sur LifeCycleOwner qui est intrinsèquement votre contrôleur d'interface utilisateur, sans cela, votre LiveData perdra son effet Live car il ne pourra pas être observé, essentiellement vos LiveData ne seront pas propagés à l'interface utilisateur.

<data>
<variable
    name="viewModel"
    type="com.felixfavour.ViewModel" />
</data>

this = UI Controller (encore une fois Activity / Fragment)


0 commentaires

0
votes

Je manquais sur le réglage

mViewDataBinding.vm = viewModel

où "vm" est la variable dans la mise en page et "viewModel" est la variable locale dans l'activité ou le fragment

De plus, comme @Menma l'a suggéré, n'oubliez pas d'ajouter

mViewDataBinding.setLifecycleOwner (ceci);


0 commentaires