代码之家  ›  专栏  ›  技术社区  ›  w00ly

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

  •  2
  • w00ly  · 技术社区  · 8 年前

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

    mockup

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

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

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

    我的活动中是否应该只有一个演示者,并将内容信息请求的数据持久化/缓存到某个位置,以便在位置更改时将其传递回播放机?

    或者,对于每个ContentInfo,最好有一个presenter,请求自己的数据,而对于播放器,最好有一个presenter,在调用play()方法时再次请求相同的数据?


    我发现 this 相关主题,但它并不真正适合我的情况,因为在内容信息片段中请求数据的同时,播放机中的数据没有更新(我在ViewPager创建片段时提取数据,以便在刷卡完成时将其加载)。

    2 回复  |  直到 8 年前
        1
  •  1
  •   Vasiliy    8 年前

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

    当ViewPager的内容更改时,只需将新内容的ID通知播放器即可。然后,播放机将从存储库中获取此内容。存储库“知道”该内容已经下载,并从数据库而不是web提供该内容。

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

        2
  •  1
  •   Shuwn Yuan Tee    8 年前

    您可以使用 Fragment 具有 setRetainInstance(true) 作为数据片段。 setRetainInstance 控制是否在活动重新创建期间保留片段实例(例如从配置更改)。

    此处的数据片段示例:

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

    假设活动类命名为 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 fragment viewpager 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;
    

    希望这对你有帮助,祝你好运!