Android MVP - 为多个片段重用共享数据

Android MVP - Reuse shared data for multiple fragments

我正在使用 MVP 构建一个 Android 应用程序。 其中一个屏幕以一种 Master/Detail 视图(嵌入播放器的内容页面)显示数据:

顶部是播放器(片段),下面是内容信息(带有片段的viewpager),用户可以在页面(ViewPager)之间滑动以在内容之间切换。当Viewpager位置改变时,播放器相应更新并开始播放当前内容。

演示者请求的数据来自存储库,具有本地(数据库)/远程(Rest API)数据源。

如何充分利用 MVP 来避免多次请求相同的数据?

我是否应该在我的 Activity 中只有一个 Presenter,并且 persist/cache 请求某处的 Content Info 数据,以便在位置改变时将其传回给播放器?

还是为每个 ContentInfo 设置一个 Presenter,请求自己的数据,为播放器设置一个 Presenter,在调用 play() 方法时再次请求相同的数据?


我找到了 相关主题,但它并不适合我的情况,因为播放器中的数据不会在内容信息片段中请求的同时更新(我我正在通过 ViewPager 获取片段的 onCreate 数据,以便在滑动完成时加载它)。

最好的方法是让各个组件从存储库请求数据,并在存储库级别处理缓存。

当ViewPager的内容发生变化时,只需通知播放器一个新内容的ID即可。然后播放器将从存储库中获取此内容。该内容已经下载的存储库 "knows" 并从数据库而不是 Web 提供。

如果数据库不够快,可以在存储库中实现内存缓存。

您可以使用 FragmentsetRetainInstance(true) 作为数据片段。 setRetainInstance 控制片段实例是否在 Activity 重新创建(例如从配置更改)中保留。

此处的数据片段示例:

public class MyDataFragment extends Fragment {
    public static MyDataFragment newInstance() {
        return new MyDataFragment();
    }

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

        // Retain this instance so it isn't destroyed when MainActivity and MainFragment change configuration.
        setRetainInstance(true);
    }    

    // Add any data you want to share across multiple fragments of same activity here
    public String myData = null;
}

假设 Activity class 被命名为 MyActivity:

public class MyActivity extends AppCompatActivity {

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

        ....

        // Build up a common data fragment to be used by multiple child view pager fragments.
        final FragmentManager fm = getSupportFragmentManager();
        MyDataFragment myDataFragment = (MyDataFragment)fm.findFragmentByTag(MY_DATA_FRAGMENT);

        if (myDataFragment == null) {
            MyDataFragment dataFragment = MyDataFragment.newInstance();
            fm.beginTransaction().add(dataFragment, MY_DATA_FRAGMENT).commit();
        }

        .....
    }

    ....

    public static final String MY_DATA_FRAGMENT = "MY_DATA_FRAGMENT";

然后在您的 player fragmentviewpager fragment 中,像这样访问数据片段:

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

    // access data fragment
    final FragmentManager fm = getFragmentManager();
    this.myDataFragment = (MyDataFragment)fm.findFragmentByTag(MyActivity.MY_DATA_FRAGMENT);

    .....
}

@Override
public void onResume() {
    super.onResume();

    if (myDataFragment.myData != null) {
        // data already exists, SKIP to make network call. Process it directly, eg: update UI
        .....
    } else {
        // fetch data from network via asynchronously task ---- [1]
        // assume upon finish, the asynchronously task will invoke "onDataLoadFinish()" method below:
        ....
    }
}

// assume this will be invoked by asynchronously network task [1] above
public void onDataLoadFinish (String data) {
    // set data to data fragment, which can be reused by multiple fragments
    this.myDataFragment.myData = data;
}

.....

private MyDataFragment myDataFragment = null;

希望对您有所帮助,祝您好运!