使用LocalBroadcastManager沟通的片段到活动 [英] Using LocalBroadcastManager to communicate from Fragment to Activity
问题描述
我已经实现的方式开始创建碎片,利用广播意图通过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屋!