Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/181.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Can';t在片段中观察ViewModel中的LiveData_Android_Android Livedata_Android Viewmodel_Mutablelivedata - Fatal编程技术网

Android Can';t在片段中观察ViewModel中的LiveData

Android Can';t在片段中观察ViewModel中的LiveData,android,android-livedata,android-viewmodel,mutablelivedata,Android,Android Livedata,Android Viewmodel,Mutablelivedata,在我的ViewPager的片段之一中有一个RecyclerView。此RecyclerView显示从服务器获取的数据。它正常工作,但我无法使用ViewModel和LiveData实现相同的功能,因为LiveData.observe方法在从ViewModel更改LiveData时没有被调用 下面是我的MonthlyOrderViewModel.java类的源代码 public class MonthlyOrderViewModel extends AndroidViewModel { priva

在我的
ViewPager
片段之一中有一个
RecyclerView
。此
RecyclerView
显示从服务器获取的数据。它正常工作,但我无法使用
ViewModel
LiveData
实现相同的功能,因为
LiveData.observe
方法在从
ViewModel
更改
LiveData
时没有被调用

下面是我的MonthlyOrderViewModel.java类的源代码

public class MonthlyOrderViewModel extends AndroidViewModel {

private Retrofit retrofit;
private RetrofitServices retrofitServices;
private MutableLiveData<MonthlyOrderHistory> monthlyOrderHistoryMutableLiveData = new MutableLiveData<>();

public MonthlyOrderViewModel(@NonNull Application application) {
    super(application);
    retrofit = RetrofitFactory.getRetrofit();
    retrofitServices = retrofit.create(RetrofitServices.class);
}

public MutableLiveData<MonthlyOrderHistory> getMonthlyOrderHistoryMutableLiveData() {
    return monthlyOrderHistoryMutableLiveData;
}
public void fetchMonthlyOrders() {
    Call<MonthlyOrderHistory> call = retrofitServices.getAllMonthlyOrderHistory(IpharmaApplication.getInstance().getLoggedInUser().getId());
    call.enqueue(new Callback<MonthlyOrderHistory>() {
        @Override
        public void onResponse(Call<MonthlyOrderHistory> call, Response<MonthlyOrderHistory> response) {

            MonthlyOrderHistory monthlyOrderHistory = response.body();
            if(monthlyOrderHistory.getStatus().equalsIgnoreCase("success")) {

                List<UserOrder> userOrders = monthlyOrderHistory.getOrders().getUserOrder();
                if(userOrders != null && userOrders.size() != 0) {
                    DefaultScheduler.INSTANCE.execute(() -> {
                        monthlyOrderHistoryMutableLiveData.postValue(monthlyOrderHistory);
                        return Unit.INSTANCE;
                    });
                }
            }
        }

        @Override
        public void onFailure(Call<MonthlyOrderHistory> call, Throwable t) {

            t.printStackTrace();
        }
    });
}

}

interface Scheduler {

    fun execute(task: () -> Unit)

    fun postToMainThread(task: () -> Unit)

    fun postDelayedToMainThread(delay: Long, task: () -> Unit)
}

//A shim [Scheduler] that by default handles operations in the [AsyncScheduler].
object DefaultScheduler : Scheduler {

    private var delegate: Scheduler = AsyncScheduler

    //Sets the new delegate scheduler, null to revert to the default async one.
    fun setDelegate(newDelegate: Scheduler?) {
        delegate = newDelegate ?: AsyncScheduler
    }

    override fun execute(task: () -> Unit) {
        delegate.execute(task)
    }

    override fun postToMainThread(task: () -> Unit) {
        delegate.postToMainThread(task)
    }

    override fun postDelayedToMainThread(delay: Long, task: () -> Unit) {
        delegate.postDelayedToMainThread(delay, task)
    }
}

//Runs tasks in a [ExecutorService] with a fixed thread of pools
internal object AsyncScheduler : Scheduler {

    private val executorService: ExecutorService = Executors.newFixedThreadPool(NUMBER_OF_THREADS)

    override fun execute(task: () -> Unit) {
        executorService.execute(task)
    }

    override fun postToMainThread(task: () -> Unit) {
        if (isMainThread()) {
            task()
        } else {
            val mainThreadHandler = Handler(Looper.getMainLooper())
            mainThreadHandler.post(task)
        }
    }

    private fun isMainThread(): Boolean {
        return Looper.getMainLooper().thread === Thread.currentThread()
    }

    override fun postDelayedToMainThread(delay: Long, task: () -> Unit) {
        val mainThreadHandler = Handler(Looper.getMainLooper())
        mainThreadHandler.postDelayed(task, delay)
    }
}

//Runs tasks synchronously.
object SyncScheduler : Scheduler {
    private val postDelayedTasks = mutableListOf<() -> Unit>()

    override fun execute(task: () -> Unit) {
        task()
    }
    override fun postToMainThread(task: () -> Unit) {
        task()
    }
    override fun postDelayedToMainThread(delay: Long, task: () -> Unit) {
        postDelayedTasks.add(task)
    }
    fun runAllScheduledPostDelayedTasks() {
        val tasks = postDelayedTasks.toList()
        clearScheduledPostdelayedTasks()
        for (task in tasks) {
            task()
        }
    }
    fun clearScheduledPostdelayedTasks() {
        postDelayedTasks.clear()
    }
}
最后,我尝试使用以下方法观察片段的
onCreateView
方法的变化:

MonthlyOrderViewModel monthlyOrderViewModel = new MonthlyOrderViewModel(getActivity().getApplication());

monthlyOrderViewModel.getMonthlyOrderHistoryMutableLiveData().observe(this, monthlyOrderHistory -> {

    monthlyOrderRecyclerView = view.findViewById(R.id.monthlyOrderRecyclerView);

    monthlyOrderRecyclerViewAdapter = new OrderHistoryRecyclerViewAdapter(getContext(), monthlyOrderHistory.getOrders().getUserOrder());

    monthlyOrderRecyclerViewAdapter.notifyDataSetChanged();

    monthlyOrderRecyclerView.setAdapter(monthlyOrderRecyclerViewAdapter);       

    monthlyOrderRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

});
我试着对它进行调试,发现改装后获取数据没有问题。但是,当我试图在片段中使用
observe
方法时,它永远不会被调用


请告诉我如何解决这个问题?任何帮助都将不胜感激。

您不应该使用
new
实例化您的
ViewModel
。您必须这样做:

MonthlyOrderViewModel monthlyOrderViewModel = ViewModelProviders.of(this).get(MonthlyOrderViewModel.class);
如果您确定在ViewModel中执行了
postValue
,那么我认为这一更改应该可以使它正常工作。还有一件事:您不应该在每次观察到的LiveData通知您某个更改时都这么做。我将在
observe()之前移动下一行

更新 正如法希姆在评论中确认的那样,问题在于正在创建同一
ViewModel
的多个实例。如果需要共享
ViewModel
的同一实例,请确保传递该ViewModel的“所有者”片段/活动的引用。例如,如果
MyActivity
有一个
MainActivityViewModel
,并且它包含一个名为
MyFragment
的子片段,那么如果该片段想要获取对其父视图模型的引用,它必须按照以下方式进行:

MainActivityViewModel mainActivityVM=ViewModelProviders
.of(getActivity())
.get(MainActivityViewModel.class);

是否在片段中为viewmodel设置了LiveCycleOwner?是的,我尝试过。我将
monthlyOrderViewModel.getMonthlyOrderHistoryMutableLiveData().observe替换为
monthlyOrderViewModel.getMonthlyOrderHistoryMutableLiveData().observe(getViewLifecycleOwner(),monthlyOrderHistory->{
,但结果相同,您在哪里调用
fetchMonthlyOrders())
触发将数据加载到您的
LiveData
?您提供的代码中没有调用它。是的,我在活动开始时使用此ViewModelProviders.of(this).get(MonthlyOrderViewModel.class).fetchMonthlyOrders();按照您的说明,我尝试了
ViewModelProviders.of(this).get(MonthlyOrderViewModel.class).observe
,但没有更改。该程序没有进入inside observe。此外,inside observe中的其余程序只是为了显示我试图用最少的代码实现的目标。如果该程序进入inside observe,我会相应地更改它们的位置。@Fahimalahmudashik我明白了……您是从片段还是视频中观察ViewModel活动?如果保存片段的活动是调用获取的活动,并且您正在片段和活动之间共享ViewModel,那么请尝试使用
MonthlyOrderViewModel MonthlyOrderViewModel=ViewModelProviders.of(getActivity()).get(MonthlyOrderViewModel.class)在片段中获取您的ViewModel;
取而代之。如果没有,您将得到两个不同的viewmodel实例抱歉迟到@dglozano。事实上,这就是问题所在,我每次都在重新创建viewmodel的新实例。请编辑您的答案并添加此信息,以便如果其他人遇到此问题,他们可以从您提供的答案中得到明确的答案泰德。我接受你的答案。非常感谢你抽出时间。@Fahimalahmudashik很高兴听到它起作用了!!!我刚刚编辑了答案:)感谢fam,这让我从整整两天的工作中解脱出来,我的数据显示在日志中,但没有显示在我的观察者中,但是在阅读了这篇文章并从拥有viewmodel的片段更改为使用activity的实例之后,我的数据都在这里了。非常感谢
monthlyOrderRecyclerView = view.findViewById(R.id.monthlyOrderRecyclerView);

monthlyOrderRecyclerViewAdapter = new OrderHistoryRecyclerViewAdapter(getContext(), monthlyOrderHistory.getOrders().getUserOrder());

monthlyOrderRecyclerView.setAdapter(monthlyOrderRecyclerViewAdapter);       

monthlyOrderRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));