使用LocalBroadcastManager沟通的片段到活动 [英] Using LocalBroadcastManager to communicate from Fragment to Activity

查看:167
本文介绍了使用LocalBroadcastManager沟通的片段到活动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经实现的方式开始创建碎片,利用广播意图通过LocalBroadcastManager告诉活动是什么片段实例片段。

I have implemented a way to initiate the creation of Fragments, from Fragments using a broadcast intent through the LocalBroadcastManager to tell the Activity what Fragment to instantiate.

我知道这是一个非常漫长金额code,但我不要求进行调试,它完美的作品,我打算 - 中接收到数据,创建可通过捆绑进行参数化和碎片不要牛逼直接实例等片段。

I know this is a terribly long amount of code, but I'm not asking for debugging, it works perfectly as I intended - the data is received, the creation can be parametrized by Bundles, and Fragments don't directly instantiate other Fragments.

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

这方法,就是创建一个片段是这样的:

This way, a Fragment that is created looks like this:

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

最初的容器的活动,可以处理的消息是这样的:

The initial container activity that can process the messages looks like this:

        Intent intent = new Intent();
        intent.setClass(this.getActivity(), ContainerActivity.class);
        intent.putExtra(FragmentCreator.fragmentCreatorKey,
                new TemplateFragment.Creator());
        startActivity(intent);

和的碎片实例等碎片是这样的:

And the Fragments "instantiate other Fragments" like this:

  Bundle bundle = new Bundle();
  bundle.putParcelable("argument", data);
  TemplateFragment.Creator creator = new TemplateFragment.Creator(bundle);
  creator.sendFragmentCreationMessage(getActivity());

和集装箱活动收到实例的请求:

And the Container Activity receives the instantiation request:

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

我的问题是,这其实是一个好主意,或者是这的过度设计一个可怕的情况(建立一个工厂的每个片段并将其发送到活动在当地广播的形式,而不是仅仅铸造最有可能持有人的活动界面的活动,并呼吁类似的功能)?

My question is, is this actually a good idea, or is this a terrible case of "over-engineering" (creating a Factory for each Fragment and sending it to the Activity in the form of a local broadcast, rather than just casting the Activity of the most possible holder activity's interface and calling the function like that)?

我的目标是,通过这种方式,我可以使用相同的活动举办分支的片段,让我不需要做每个菜单点。而不仅仅是重复使用相同的活动,并划分所有的逻辑成了碎片。 (目前,它不支持基于方向的布局组织,我看到的缺点 - 并且也是这样,每个片段需要持有一个静态的创造者,这是额外的'样板code')

My goal was that this way, I can use the same Activity for holding "branch" fragments, so that I don't need to make one for each menu point. Rather than just re-use the same activity, and divide all logic into fragments. (Currently it doesn't support orientation-based layout organization, I see that downside - and also that this way each Fragment needs to hold a static creator, which is extra 'boilerplate code').

如果你知道我为什么不应该使用本地广播经理这个答案,我会很高兴听到回应。我认为这是pretty的整齐,但有它只是过于复杂一些简单的机会。

If you know the answer why I shouldn't be using the local broadcast manager for this, I'll be happy to hear the response. I think it's pretty neat, but there's a chance it's just overcomplicating something simple.

推荐答案

您可以使用接口作为片段重用性的它,主要目标是维持。您可以通过使用以下实施活动片段或片段,片段之间的沟通:

You can use Interface for it so main objective of Fragment re-usability is maintained. You can implement communication between Activity-Fragment OR Fragment-Fragment via using following :

这篇关于使用LocalBroadcastManager沟通的片段到活动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆