在ViewModel中加载已在SplashActvity中获取的数据

时间:2018-10-06 11:37:40

标签: android android-fragments android-activity mvvm android-viewmodel

我是ViewModel的新手,我知道这是与片段进行通信的强大而简便的方法。

我的问题如下:如何在mainActivity的ViewModel中加载在SplashActivity中检索到的数据?

我的应用程序结构如下:

  1. SplashActivity:检索经过改造的数据并将其存储到列表中
  2. 主要活动:包含两个以不同方式显示数据的片段

这是一段显示我的实现的代码。

SplashActivity

public class SplashActivity extends AppCompatActivity {

    private final String TAG = "TAG.SplashActivity";
    public static List<Toilet> toiletList = new ArrayList<>(); // HERE IS THE DATA I WANT TO 
    RETRIEVE IN THE MAIN ACTIVITY

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        /*Create handle for the RetrofitInstance interface*/
        GetDataService service = ...;
        // MY STUFF RETROFIT including
        Intent intent = new Intent(getApplicationContext(), MainActivity.class);
        intent.putExtra("toiletList", (Serializable) toiletList);
        startActivity(intent);
        finish();
    }
}

MainActivity

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

    private final String TAG = getClass().getName();
    private List<Toilet> toiletList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent= getIntent();
        Serializable s = intent.getSerializableExtra("toiletList");
        // Check type and cast
        if (s instanceof List<?>) {
            for (Object o : (List<?>) s) {
                if (o instanceof Toilet) {
                    toiletList.add((Toilet) o);
                }
            }
        }

        // SETTING UP FRAGMENTS
    }
}

FragmentExample

public class MainFragment extends Fragment {

    public static List<Toilet> toiletArrayList = new ArrayList<>();
    private final String TAG = this.getClass().getName();

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_main, container, false);

       // SETTING UP UI
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ToiletListViewModel model = ViewModelProviders.of(this).get(ToiletListViewModel.class);
        model.getToiletList().observe(this, new Observer<List<Toilet>>() {
            @Override
            public void onChanged(@Nullable List<Toilet> toilets) {
                //  update UI
            }
        });
    }
}

ToiletListViewModel

public class ToiletListViewModel extends ViewModel {

    private final String TAG = getClass().getName();
    private MutableLiveData<List<Toilet>> toiletList;

    public LiveData<List<Toilet>> getToiletList() {
        if (toiletList == null) {
            toiletList = new MutableLiveData<>();
            loadToilets();
        }
        return toiletList;
    }

    private void loadToilets() {
        // asynchronously fetch toilets
        // HERE IS MY PROBLEM : How to access the toiletList retrieved
        in the SplashActivity ?
        toiletList.setValue(SplashActivity.toiletList);
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        Log.d(TAG, "onCleared() called");
    }
}

我希望这很清楚。如果您需要任何进一步的信息,请随意询问!

最佳

3 个答案:

答案 0 :(得分:3)

您可以在ToiletListViewModel及其MainActivity之间share Fragment

因此,您需要为ViewModel提供MainActivity范围(这意味着您将ViewModel的生命周期绑定到您的Activity)并调用initToilets然后是child片段可以轻松地检索此ViewModel并在其LiveData上进行观察。

ToiletListViewModel:

public class ToiletListViewModel extends ViewModel {

    private MutableLiveData<List<Toilet>> toiletList = new MutableLiveData();

    public LiveData<List<Toilet>> getToiletList() {
        return toiletList;
    }

    private void initToilets(List<Toilet> toilets) {
        toiletList.setValue(toilets);
    }


}

MainActivity:

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

    private final String TAG = getClass().getName();
    private List<Toilet> toiletList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent= getIntent();
        Serializable s = intent.getSerializableExtra("toiletList");
        // Check type and cast
        if (s instanceof List<?>) {
            for (Object o : (List<?>) s) {
                if (o instanceof Toilet) {
                    toiletList.add((Toilet) o);
                }
            }
        }
     ToiletListViewModel vm = ViewModelProviders.of(this).get(ToiletListViewModel.class);
     vm.initToilets(toiletList);
        // SETTING UP FRAGMENTS
    }
}

因此,当调用setValue时,将通知监听toiletList实时数据的片段。

注意:

您可以创建共享的ViewModel,而无需在MainActivity上提供它,而不用调用

ViewModelProviders.of(this).get(ToiletListViewModel.class);

在您的片段中做

ViewModelProviders.of(getActivity()).get(ToiletListViewModel.class);

答案 1 :(得分:0)

有两个建议:

您可以将数据直接添加到列表中(关闭主题)

if (s instanceof List<?>) {
    for (Object o : (List<?>) s) {
        if (o instanceof Toilet) {
            toiletList.add((Toilet) o);
        }
    }
}

使用它代替:

if (s instanceof List<?>) {
    toiletList.addAll((List<Toilet>)s);
}

返回主主题:

您可以使用ViewModel个Activity实例代替Fragment中的这个实例。怎么样?

参加ViewModel的活动,如下所示,

ToiletListViewModel model = ViewModelProviders.of(this).get(ToiletListViewModel.class);

Fragment的分享是这样的

ToiletListViewModel model = ViewModelProviders.of(getActivity()).get(ToiletListViewModel.class);

这将在活动中的各个片段之间共享您的ViewModel,并观察您的livedata

答案 2 :(得分:0)

为了在视图模型中使用,您需要在活动中存储对该实例的引用,然后与它们交互以修改数据。

我首先建议您阅读developer guide on View Model

设置并在活动和片段中存储对模型的引用时,可以向模型添加一个方法,例如setToilets(List<Toilet>),该方法将更新“视图模型”中的厕所,并调用{{ 1}}或存储原始厕所,以便loadToilets()以后可以访问它,现在可以装载哪些厕所。
然后,您可以编写相应的方法来访问要从其他类公开的所有数据,就像使用loadToilets()方法一样。