将一个方法从一个活动调用到另一个活动的一个片段。什么是正确的方法?

时间:2014-11-25 19:26:07

标签: android android-activity android-fragments callback

这可能已经回答了,但我仍然对这样的功能感到不安。假设我有活动A 活动B 。 B持有viewpager,里面有几个片段。我想在活动A 中的活动B 所持有的片段中调用一个函数。

我多次使用回调来在活动和片段之间进行通信,但每次只有片段及其持有者活动。我不想创建一个静态方法(回调监听器无论如何也不能是静态的)所以它让我头疼。在片段中创建静态方法并从另一个调用它的简单静态解决方案实际上非常有效,但我不确定它是否是一个好主意,因为我需要更改静态的几个东西。

因此,活动B 与其片段之间的通信是可以的,但我无法在活动A 中调用此方法。

活动B:

public class ActivityB extends FragmentActivity implements Fragment1.OnWhateverListener                           
                          {  
...

@Override
    public void onWhateverSelected(int position) {  
         //stuff, here I can call any function in Fragment 1
    }

}

以下代码段是一个错误的解决方案(甚至不起作用),但可以更好地了解我想要做的事情。

活动A:

ActivityB ab = new ActivityB ();
ab.onWhateverSelected(number);

那我该怎么做呢? 谢谢!

编辑

活动A:我打电话的方法

  Bundle args = new Bundle();
   args.putString("ID", id); // the data to send
   Intent frag_args = new Intent(Intent.ACTION_VIEW);
   frag_args.setClass(this, MainActivity.class);
   frag_args.putExtra("args", args);
   startActivity(frag_args);

活动B:

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    ...
    processIntent(getIntent()); //last line of onCreate, always gets called here
    }


     @Override
     public void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
            processIntent(intent); // this never gets called here only in OnCreate
     }

     private void processIntent(Intent intent) {
                Bundle args = intent.getBundleExtra("args");
                if (args != null) { // check if ActivityB is started to pass data to fragments
                    String id = args.getString("ID");


            Log.i("ID_FROM", "id: " + id);   //works well
                        if (id != null) {
                          List<Fragment> fragments = new ArrayList<Fragment>();
                          fragments = getSupportFragmentManager().getFragments();
                       //NULLPOINTER for the following line 
                          FragmentMainDiscover fr = (FragmentMainDiscover) fragments.get(0);  
                          fr.RefreshHoverView(id);
                        }
                    }
                }

1 个答案:

答案 0 :(得分:0)

你是正确的远离静态。对于可能在屏幕上或可能不在屏幕上的视觉对象,风险太大。

我建议浏览活动B,因为它是目标片段的父级。创建一个启动活动B的Intent,并包含一个intent extra,它告诉活动B它应该对目标片段做什么。然后活动B可以确保片段正在显示,并将信息传递给它。

将信息传递给片段的另一个想法是使用setArguments,而不是直接调用。这是一个很好的方法,因为如果活动及其片段从内存中删除,Android将自动恢复参数。

这有意义吗?你想要代码吗?

修改

要使用参数,您仍然需要让活动A通过活动B.这是因为活动A不知道活动B及其所有碎片是否正在运行,除非它向它发送一个Intent。但是您可以通过将它们放在intent中来包含针对片段的数据。像这样:

public class ActivityA extends Activity {
    public static final String KEY_FRAG = "frag"; // tells activity which fragment gets the args
    public static final String KEY_ARGS = "args";
    public static final String KEY_MY_PROPERTY = "myProperty";

    public void foo() {
        Bundle args = new Bundle();
        args.putString(KEY_FRAG, "frag1Tag"); // which fragment gets the data
        args.putCharSequence(KEY_MY_PROPERTY, "someValue"); // the data to send

        // Send data via an Intent, to make sure ActivityB is running
        Intent frag_args = new Intent(Intent.ACTION_VIEW);
        frag_args.setClass(this, ActivityB.class);
        frag_args.putExtra(KEY_ARGS, args);
        startActivity(frag_args);
    }
}

public class ActivityB extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //TODO configure activity including fragments
        processIntent(getIntent()); // this call is in case ActivityB was not yet running
    }

    @Override
    public void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        processIntent(intent); // this call is in case ActivityB was already running 
    }

    private void processIntent(Intent intent) {
        Bundle args = intent.getBundleExtra(ActivityA.KEY_ARGS);
        if (args != null) { // check if ActivityB is started to pass data to fragments
            String fragTag = args.getString(ActivityA.KEY_FRAG);
            if (fragTag != null) {
                Fragment frag = getSupportFragmentManager().findFragmentByTag(fragTag);
                frag.setArguments(args);
                //TODO either show the fragment, or call a method on it to let it know it has new arguments
            }
        }
    }
}

public class Fragment1 extends Fragment {
    public static final String TAG = "frag1Tag";
    @Override
    public void onResume() {
        super.onResume();
        Bundle args = getArguments();
        String value = args.getString(ActivityA.KEY_MY_PROPERTY);
        ...
    }
}