简体   繁体   English

在Flow中使用Dispatcher的正确方法?

[英]Proper way to use Dispatcher in Flow?

I have a simple two screen app. 我有一个简单的两屏应用程序。 The first screen presents the user with login options and the second screen is where they see the content upon login. 第一个屏幕为用户提供登录选项,第二个屏幕是用户在登录时看到内容的位置。

Once the user logs in, I set the key with Flow.get( view ).set( Screens.CHAT ) . 用户登录后,我用Flow.get( view ).set( Screens.CHAT )设置密钥。

All is nice and dandy but I run into a problem that makes my view look like this: 一切都很好,但我遇到了一个问题,使我的观点看起来像这样:

在此处输入图片说明

This re-drawing of view happens when the user leaves the app by pressing home button and then comes back to it (basically after onRestart( ) ). 当用户通过按下主屏幕按钮离开应用程序然后返回到应用程序时(基本上在onRestart( ) ),就会发生这种视图onRestart( ) The un-populated RecyclerView is added to the view hierarchy again. 未填充的RecyclerView再次添加到视图层次结构中。

My Dispatcher logic is this: 我的Dispatcher逻辑是这样的:

public void dispatch(Traversal traversal, TraversalCallback callback) {
    Object dest = traversal.destination.top();
    Object source = traversal.origin == null ? null : traversal.origin.top();

    ViewGroup root = (ViewGroup) activity.findViewById(R.id.root);

    if (traversal.origin != null) {
        int childCount = root.getChildCount();
        // Our container has a root view with an ImageView in it.
        // If child count > 1, we need to remove the child at position = 1
        // because ImageView is at position = 0
        if (childCount > 1) {
            // save state
            traversal.getState(traversal.origin.top()).save(root.getChildAt(1));
            // remove the added views
            removeAllViewsAfter(root,0);
        }
    }

    @LayoutRes int layout;
    if(dest.equals(Screens.WELCOME)){
        layout = R.layout.view_welcome;
    }else if(dest.equals(Screens.CHAT)){
        layout = R.layout.view_chat;
    }else{
        throw new IllegalArgumentException("Unrecognized Screen");
    }

    View incomingView = LayoutInflater
            .from(traversal.createContext(dest, activity))
            .inflate(layout, root, false);
    traversal.getState( traversal.destination.top() ).restore(incomingView);
    root.addView( incomingView );
    callback.onTraversalCompleted();
}
//----------------------------------------------------------------------------------------------
private void removeAllViewsAfter(ViewGroup root, int index){
    for( int i = root.getChildCount() - 1; i > index; i-- ){
        root.removeViewAt( i );
    }
}
//----------------------------------------------------------------------------------------------  

What do I change in my Dispatcher logic to avoid the same layout from being inflated and added again ? 我应该在Dispatcher逻辑中进行哪些更改,以防止相同的布局被夸大并再次添加?

The problem is that your root ViewGroup isn't getting cleared. 问题是您的root ViewGroup没有被清除。

Here's diff that I believe will fix your issue ( < remove, > add). 我相信这里的差异会解决您的问题( <删除, >添加)。

12c12
<         if (childCount > 1) {
---
>         if (childCount > 0) {
14c14
<             traversal.getState(traversal.origin.top()).save(root.getChildAt(1));
---
>             traversal.getState(traversal.origin.top()).save(root.getChildAt(0));
16c16
<             removeAllViewsAfter(root,0);
---
>             frame.removeAllViews();
36,42d35
< //----------------------------------------------------------------------------------------------
< private void removeAllViewsAfter(ViewGroup root, int index){
<     for( int i = root.getChildCount() - 1; i > index; i-- ){
<         root.removeViewAt( i );
<     }
< }
< //----------------------------------------------------------------------------------------------  

The Flow repo has an example with something pretty close to what you already have. Flow回购提供了一个示例,示例非常接近您已有的示例

@Override
public void dispatch(@NonNull Traversal traversal, @NonNull TraversalCallback callback) {
  Log.d("BasicDispatcher", "dispatching " + traversal);
  Object destKey = traversal.destination.top();

  ViewGroup frame = (ViewGroup) activity.findViewById(R.id.basic_activity_frame);

  // We're already showing something, clean it up.
  if (frame.getChildCount() > 0) {
    final View currentView = frame.getChildAt(0);

    // Save the outgoing view state.
    if (traversal.origin != null) {
      traversal.getState(traversal.origin.top()).save(currentView);
    }

    // Short circuit if we would just be showing the same view again.
    final Object currentKey = Flow.getKey(currentView);
    if (destKey.equals(currentKey)) {
      callback.onTraversalCompleted();
      return;
    }

    frame.removeAllViews();
  }

  @LayoutRes final int layout;
  if (destKey instanceof HelloScreen) {
    layout = R.layout.hello_screen;
  } else if (destKey instanceof WelcomeScreen) {
    layout = R.layout.welcome_screen;
  } else {
    throw new AssertionError("Unrecognized screen " + destKey);
  }

  View incomingView = LayoutInflater.from(traversal.createContext(destKey, activity)) //
      .inflate(layout, frame, false);

  frame.addView(incomingView);
  traversal.getState(traversal.destination.top()).restore(incomingView);

  callback.onTraversalCompleted();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM