【问题标题】:returning an object from an android ViewModel to the fragment from a callback function从回调函数将对象从 android ViewModel 返回到片段
【发布时间】:2019-05-17 03:53:21
【问题描述】:

我在android中使用ViewModel来获取一个对象,然后将它传递给一个片段来更新UI组件。我试图异步获取对象的值,然后将对象从回调函数传递给片段。我在回调和异步任务中已经有了对象的非空值。我只是无法通过调用片段 java 代码中的函数将对象发送到片段。这是代码sn-p

ViewModel的代码sn-p

EventViewModel.java

class EventViewModel extends AndroidViewModel {

  private OnEventListener mListener;
  Obj obj;

  //setting the listener
  public void registerOnEventListener(OnEventListener mListener){
    this.mListener = mListener;
  }

  public void getObj(){

     new Thread(new Runnable() {
        @Override
        public void run() {
          //code to obtain non-null value of object
          //& obtains non-null value here
          obj = some-non-null-value

          if(mListener != null){
                //invoke the callback
                mListener.onEvent();
          }
        }
      });
  }

   interface OnEventListener(){
     Obj onEvent();
   }

   class A implements  OnEventListener {

     @Override
     public Obj onEvent() {

       System.out.println(obj.property1); //obj is non-null here

       //....
       return obj;
   }

 }
}

我要将对象发送到的fragment 的代码 sn-p

EventFragment.java

public class EventFragment extends Fragment {

 private EventViewModel vm;

 @Override
 public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    vm = ViewModelProviders.of(this).get(EventViewModel.class);

    EventViewModel.OnEventListener mListener = vm. new A();
    vm.registerOnEventListener(mListener);
    vm.getObj();
    Obj o = mListener.getEvent()  //shows error as 'Incompatible Types'
                                  //so o is also null   
   }
}

现在我知道我不能在getObj() 方法中直接返回obj,它会在obj 被赋予非空值之前返回,即在异步任务结束之前。在尝试上述方法时,EventFragment 中的对象 o 始终保持为空。所以,请告诉一个将对象发送到片段EventFragment.java 的方法。如果我需要发布更多代码,请指出。提前致谢。

【问题讨论】:

  • 为什么不让你的ViewModel 持有MutableLiveData<Obj>,拥有observe() 的片段LiveData,然后从你的后台线程更新MutableLiveData
  • 因为我试图获取对象的方法的返回类型为Object,我无法将其转换为MutableLiveData<Obj>
  • 您不会“转换”它。您可以在 MutableLiveData<Obj> 上调用 postValue() 来发布它。

标签: java android android-fragments callback android-viewmodel


【解决方案1】:

使用LiveData:

class EventViewModel extends AndroidViewModel {
  private MutableLiveData<Obj> liveObjects = new MutableLiveData<>();

  LiveData<Obj> getObjects() {
    return liveObjects;
  }

  public void loadObject(){
     new Thread(new Runnable() {
        @Override
        public void run() {
          Obj object = // TODO get the value

          liveObjects.postValue(object);
        }
      }).start();
  }
}

public class EventFragment extends Fragment {

 private EventViewModel vm;

 @Override
 public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    vm = ViewModelProviders.of(this).get(EventViewModel.class);

    vm.getObjects().observe(this, new Observer<Obj>() {
        @Override
        public void onChanged(@Nullable final Obj newValue) {
            // TODO something useful
        }
    });
}

然后,在适当的时候,在EventViewModel 上调用loadObject() 以触发新对象的后台工作和交付。

【讨论】:

  • loadObject() 必须在设置Observer 之前被调用,因为我得到一个NullPointerException 因为我试图调用Observer观察一个空值。什么时候应该调用loadObject()
  • @aQwusjargon:“我正在尝试调用 Observer 来观察空值”——不,您需要处理 null 值,例如通过 if (newValue != null) { // TODO something useful }
  • 只有当我们能够观察到newValue 时,我们才能检查(newValue != null),但我的应用程序一启动就崩溃,显示NullPointerExcpetion,这是代码试图观察空值,因为在调用loadObject() 之前getObjects() 为空,并且当我通过loadObject() 获得非空值时,调用getObjects() 以进行观察getObjects() 是否必须异步调用?
  • @aQwusjargon: "since getObjects() is null" -- 抱歉,我忘记在示例代码中初始化 liveObjects 字段。查看更新的代码。
  • 我根据obj 的空值或空值将两个单独的命令打印到控制台,但目前这两个命令都没有打印到控制台。我在EventViewModel 类中将loadObject() 称为public EventViewModel(@NonNull Application application) { super(application); loadObject(); }
猜你喜欢
  • 2016-03-17
  • 2012-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多