首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用LocalBroadcastManager从片段到活动进行通信

问使用LocalBroadcastManager从片段到活动进行通信
EN

Stack Overflow用户
提问于 2014-06-06 11:45:58
回答 2查看 7.3K关注 0票数 0

编辑:这个问题是在我刚开始开发Android应用程序的时候,作为我第一个Android项目的一部分创建的。出于历史原因,我保留它,但您应该考虑使用EventBus或RxJava。这是一个巨大的混乱。

请不要考虑使用这个。谢谢。

事实上,如果您想要一些很酷的东西来解决使用一个带有多个“片段”的活动的问题,那么使用无流与自定义视图组。

我已经实现了一种从片段开始创建片段的方法,通过LocalBroadcastManager使用广播意图告诉活动要实例化哪个片段。

我知道这是一段非常长的代码,但我并不要求调试,它按照我的意图完美地工作--数据被接收,创建可以被Bundles参数化,片段不会直接实例化其他片段。

代码语言:javascript
复制
public abstract class FragmentCreator implements Parcelable
{
public static String fragmentCreatorKey = "fragmentCreator";
public static String fragmentCreationBroadcastMessage = "fragment-creation";
public static String fragmentDialogCreationBroadcastMessage = "fragment-dialog-creation";

protected Bundle arguments;
protected Boolean hasBundle;

public FragmentCreator(Bundle arguments, boolean hasBundle)
{
    this.arguments = arguments;
    this.hasBundle = hasBundle;
}

protected FragmentCreator(Parcel in)
{
    hasBundle = (Boolean) in.readSerializable();
    if (hasBundle == true && arguments == null)
    {
        arguments = in.readBundle();
    }
}

public Fragment createFragment()
{
    Fragment fragment = instantiateFragment();
    if (arguments != null)
    {
        fragment.setArguments(arguments);
    }
    return fragment;
}

protected abstract Fragment instantiateFragment();

@Override
public int describeContents()
{
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags)
{
    dest.writeSerializable(hasBundle);
    if (arguments != null)
    {
        arguments.writeToParcel(dest, 0);
    }
}

public void sendFragmentCreationMessage(Context context)
{
    Intent intent = new Intent(FragmentCreator.fragmentCreationBroadcastMessage);
    intent.putExtra(FragmentCreator.fragmentCreatorKey, this);
    LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}

public void sendDialogFragmentCreationMessage(Context context)
{
    Intent intent = new Intent(FragmentCreator.fragmentDialogCreationBroadcastMessage);
    intent.putExtra(FragmentCreator.fragmentCreatorKey, this);
    LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
}

这样,创建的片段如下所示:

代码语言:javascript
复制
public class TemplateFragment extends Fragment implements GetActionBarTitle, View.OnClickListener
{
 private int titleId;

public TemplateFragment()
{
    titleId = R.string.app_name;
}

@Override
public int getActionBarTitleId()
{
    return titleId;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    View rootView = inflater.inflate(R.layout.fragment_template, container, false);
    return rootView;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
    super.onViewCreated(view, savedInstanceState);
}

@Override
public void onClick(View v)
{
}

public static class Creator extends FragmentCreator
{
    public Creator()
    {
        super(null, false);
    }

    public Creator(Bundle bundle)
    {
        super(bundle, true);
    }

    protected Creator(Parcel in)
    {
        super(in);
    }

    @Override
    protected Fragment instantiateFragment()
    {
        return new TemplateFragment();
    }

    @SuppressWarnings("unused")
    public static final Parcelable.Creator<TemplateFragment.Creator> CREATOR = new Parcelable.Creator<TemplateFragment.Creator>()
    {
        @Override
        public TemplateFragment.Creator createFromParcel(Parcel in)
        {
            return new TemplateFragment.Creator(in);
        }

        @Override
        public TemplateFragment.Creator[] newArray(int size)
        {
            return new TemplateFragment.Creator[size];
        }
    };
}
}

可以处理消息的初始容器活动如下所示:

代码语言:javascript
复制
        Intent intent = new Intent();
        intent.setClass(this.getActivity(), ContainerActivity.class);
        intent.putExtra(FragmentCreator.fragmentCreatorKey,
                new TemplateFragment.Creator());
        startActivity(intent);

这些片段“实例化其他片段”如下:

代码语言:javascript
复制
  Bundle bundle = new Bundle();
  bundle.putParcelable("argument", data);
  TemplateFragment.Creator creator = new TemplateFragment.Creator(bundle);
  creator.sendFragmentCreationMessage(getActivity());

容器活动接收实例化请求:

代码语言:javascript
复制
public class ContainerActivity extends ActionBarActivity implements SetFragment, ShowDialog
{
private BroadcastReceiver mFragmentCreationMessageReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        setFragment((FragmentCreator) intent.getParcelableExtra(FragmentCreator.fragmentCreatorKey));
    }
};

private BroadcastReceiver mFragmentDialogCreationMessageReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        showDialog((FragmentCreator) intent.getParcelableExtra(FragmentCreator.fragmentCreatorKey));
    }
};

@Override
public void onCreate(Bundle saveInstanceState)
{
    super.onCreate(saveInstanceState);
    this.setContentView(R.layout.activity_container);
    getActionBar().setDisplayHomeAsUpEnabled(true);
    if (saveInstanceState == null)
    {
        Fragment fragment = ((FragmentCreator) getIntent().getParcelableExtra(
                FragmentCreator.fragmentCreatorKey)).createFragment();
        if (fragment != null)
        {
            replaceFragment(fragment);
        }
    }
    else
    {
        this.getActionBar()
                .setTitle(
                        ((GetActionBarTitle) (this.getSupportFragmentManager()
                                .findFragmentById(R.id.activity_container_container)))
                                .getActionBarTitleId());
    }
    getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener()
    {
        public void onBackStackChanged()
        {
            int backCount = getSupportFragmentManager().getBackStackEntryCount();
            if (backCount == 0)
            {
                finish();
            }
        }
    });
}

@Override
protected void onResume()
{
    LocalBroadcastManager.getInstance(this).registerReceiver(mFragmentCreationMessageReceiver,
            new IntentFilter(FragmentCreator.fragmentCreationBroadcastMessage));
    LocalBroadcastManager.getInstance(this).registerReceiver(mFragmentDialogCreationMessageReceiver,
            new IntentFilter(FragmentCreator.fragmentDialogCreationBroadcastMessage));
    super.onResume();
}

@Override
protected void onPause()
{
    super.onPause();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(mFragmentCreationMessageReceiver);
    LocalBroadcastManager.getInstance(this).unregisterReceiver(
            mFragmentDialogCreationMessageReceiver);
}

@Override
public void setFragment(FragmentCreator fragmentCreator)
{
    Fragment fragment = fragmentCreator.createFragment();
    replaceFragment(fragment);
}

public void replaceFragment(Fragment fragment)
{
    if (fragment != null)
    {
        this.setTitle(((GetActionBarTitle) fragment).getActionBarTitleId());
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.activity_container_container, fragment).addToBackStack(null).commit();
    }
}

@Override
public void showDialog(FragmentCreator fragmentCreator)
{
    FragmentManager fm = getSupportFragmentManager();
    Fragment fragment = fragmentCreator.createFragment();
    if (fragment instanceof DialogFragment)
    {
        DialogFragment df = (DialogFragment) fragment;
        df.show(fm, "dialog");
    }
    else
    {
        Log.e(this.getClass().getSimpleName(), "showDialog() called with non-dialog parameter!");
    }
}

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    if (item.getItemId() == android.R.id.home)
    {
        this.onBackPressed();
    }
    return super.onOptionsItemSelected(item);
}
}

我的问题是,这实际上是一个好主意吗,还是“过度工程”(为每个片段创建一个工厂,并以本地广播的形式发送给活动,而不只是将最可能的holder活动界面的活动转换成这样的函数)?

我的目标是这样,我可以使用相同的活动来保存“分支”片段,这样我就不需要为每个菜单项创建一个。而不是仅仅重复使用相同的活动,并将所有的逻辑分割成片段。(目前它不支持基于方向的布局组织,我看到了它的缺点--而且这样每个片段都需要保存一个静态创建者,这是额外的“样板代码”)。

如果你知道为什么我不应该用本地广播管理器来做这件事,我会很高兴听到你的回应。我认为它很整洁,但它有可能会使一些简单的事情变得过于复杂。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-06-06 13:30:13

您可以使用接口来实现它,从而维护碎片可重用性的主要目标。您可以使用以下方法实现活动片段或片段片段之间的通信:

​

​

票数 4
EN

Stack Overflow用户

发布于 2014-06-06 12:28:36

我认为您的moto是片段,可以与其活动和其他片段进行通信。如果是这样的话,请通过。

为了允许片段与其活动进行通信,您可以在片段类中定义一个接口并在活动中实现它。片段在其onAttach()生命周期方法中捕获接口实现,然后调用接口方法以便与活动通信。

例子:

In片段

代码语言:javascript
复制
    public class HeadlinesFragment extends ListFragment {

    OnHeadlineSelectedListener mCallback;

    public interface OnHeadlineSelectedListener {        
    public void onArticleSelected(int position);    
    }

   @Override   
   public void onAttach(Activity activity) {        
   super.onAttach(activity);
   mCallback = (OnHeadlineSelectedListener) activity;
   }
   @Override    
   public void onListItemClick(ListView l, View v, int position, long id) {
   mCallback.onArticleSelected(position);    
  }
  }

# In Activity

    public static class MainActivity extends Activity  implements HeadlinesFragment.OnHeadlineSelectedListener{
 public void onArticleSelected(int position) {
  // Do something here
 }
 }

链接:http://developer.android.com/training/basics/fragments/communicating.html

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24081101

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档