我正在尝试在我的程序中两个片段之间传递数据。这只是一个简单的字符串,存储在列表中。该列表在片段A中被公开,当用户点击列表项时,我需要它出现在片段B中。内容提供程序似乎仅支持ID,所以那样行不通。有什么建议吗?
我正在尝试在我的程序中两个片段之间传递数据。这只是一个简单的字符串,存储在列表中。该列表在片段A中被公开,当用户点击列表项时,我需要它出现在片段B中。内容提供程序似乎仅支持ID,所以那样行不通。有什么建议吗?
为什么不使用 Bundle。从您的第一个 fragment 开始,这是如何设置它:
Fragment fragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putInt(key, value);
fragment.setArguments(bundle);
然后在您的第二个片段中,使用以下方式检索数据:
Bundle bundle = this.getArguments();
int myInt = bundle.getInt(key, defaultValue);
Bundle拥有许多数据类型的方法。请参见http://developer.android.com/reference/android/os/Bundle.html
如果您使用Roboguice,您可以使用Roboguice中的EventManager来传递数据,而无需使用Activity作为接口。在我看来,这非常干净。
如果您不使用Roboguice,则也可以使用Otto作为事件总线:http://square.github.com/otto/
更新20150909:现在也可以使用Green Robot Event Bus或RxJava,具体取决于您的用例。
假设你有一个名为AB的Activity,控制着A和B两个Fragment。 在Fragment A中,你需要一个接口,Activity AB可以实现它。 在这个Android示例代码里,他们用了:
private Callbacks mCallbacks = sDummyCallbacks;
/*一个回调接口,所有包含该Fragment的Activity都必须实现它。这种机制允许Activity被通知项目的选择。*/
public interface Callbacks {
/*Callback for when an item has been selected. */
public void onItemSelected(String id);
}
/*A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity. */
private static Callbacks sDummyCallbacks = new Callbacks() {
@Override
public void onItemSelected(String id) {
}
};
回调接口被放置在其中一个Fragment中(假设为Fragment A)。我认为这个Callbacks接口的目的就像是一个嵌套类在Frag A中,任何Activity都可以实现它。所以如果Fragment A象一台电视,Callbacks就像是电视遥控器(接口),允许Activity AB使用Fragment A。我可能对细节理解有误,因为我刚开始学习,但我确保我的程序在所有屏幕尺寸上都完美运行了,并且我用的就是这个方法。
所以,在Fragment A中,我们有: (我从Android的示例程序中找到的)
@Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
//mCallbacks.onItemSelected( PUT YOUR SHIT HERE. int, String, etc.);
//mCallbacks.onItemSelected (Object);
}
在 Activity AB 中,我们重写 onItemSelected 方法:
public class AB extends FragmentActivity implements ItemListFragment.Callbacks {
//...
@Override
//public void onItemSelected (CATCH YOUR SHIT HERE) {
//public void onItemSelected (Object obj) {
public void onItemSelected(String id) {
//Pass Data to Fragment B. For example:
Bundle arguments = new Bundle();
arguments.putString(“FragmentB_package”, id);
FragmentB fragment = new FragmentB();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction().replace(R.id.item_detail_container, fragment).commit();
}
所以在 Activity AB 中,你基本上把一切都放进 Bundle 中并将其传递给 B。如果您不确定如何使用 Bundle,请查看该类。
我基本上是按照 Android 提供的示例代码进行操作的。其中包含 DummyContent 的那个。当您创建一个新的 Android 应用程序包时,它的名称为 MasterDetailFlow。
1- 第一种方法是定义一个接口
public interface OnMessage{
void sendMessage(int fragmentId, String message);
}
public interface OnReceive{
void onReceive(String message);
}
2- 在您的活动中实现OnMessage接口
public class MyActivity implements OnMessage {
...
@Override
public void sendMessage(int fragmentId, String message){
Fragment fragment = getSupportFragmentManager().findFragmentById(fragmentId);
((OnReceive) fragment).sendMessage();
}
}
3- 在你的fragment中实现OnReceive接口
public class MyFragment implements OnReceive{
...
@Override
public void onReceive(String message){
myTextView.setText("Received message:" + message);
}
}
这是处理片段之间消息传递的基本版本。
另一种处理片段之间数据传递的方法是使用事件总线。
1- 注册/注销到事件总线
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
2- 定义一个事件类
public class Message{
public final String message;
public Message(String message){
this.message = message;
}
}
3- 在您的应用程序中的任何位置发布此事件
EventBus.getDefault().post(new Message("hello world"));
4- 订阅该事件以在您的 Fragment 中接收它
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(Message event){
mytextview.setText(event.message);
}
关于事件总线模式的更多细节、使用案例和示例项目,请参考此链接。
public class FragmentB {
private void sendMessage() {
Intent intent = new Intent("custom-event-name");
intent.putExtra("message", "your message");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
public class FragmentA {
@Override
public void onCreate(Bundle savedInstanceState) {
...
// Register receiver
LocalBroadcastManager.getInstance(this).registerReceiver(receiver,
new IntentFilter("custom-event-name"));
}
// This will be called whenever an Intent with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("message");
}
};
}
这取决于片段的结构。如果您可以将Fragment Class B的某些方法以及目标TextView对象设置为静态,则可以直接在Fragment Class A上调用该方法。这比侦听器更好,因为该方法会立即执行,我们不需要额外的任务来负责在整个活动期间进行侦听。请参见下面的示例:
Fragment_class_B.setmyText(String yourstring);
public static void setmyText(final String string) {
myTextView.setText(string);
}
只需确保在Fragment B中将myTextView设置为静态,并在Fragment A中正确导入Fragment B类即可。最近我在我的项目上执行了这个过程,它有效了。希望对你有所帮助。
public class MainActivity extends Activity implements SendFragment.StartCommunication
{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void setComm(String msg) {
// TODO Auto-generated method stub
DisplayFragment mDisplayFragment = (DisplayFragment)getFragmentManager().findFragmentById(R.id.fragment2);
if(mDisplayFragment != null && mDisplayFragment.isInLayout())
{
mDisplayFragment.setText(msg);
}
else
{
Toast.makeText(this, "Error Sending Message", Toast.LENGTH_SHORT).show();
}
}
}
2) 发送者片段(片段到活动)
public class SendFragment extends Fragment
{
StartCommunication mStartCommunicationListner;
String msg = "hi";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View mView = (View) inflater.inflate(R.layout.send_fragment, container);
final EditText mEditText = (EditText)mView.findViewById(R.id.editText1);
Button mButton = (Button) mView.findViewById(R.id.button1);
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
msg = mEditText.getText().toString();
sendMessage();
}
});
return mView;
}
interface StartCommunication
{
public void setComm(String msg);
}
@Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
if(activity instanceof StartCommunication)
{
mStartCommunicationListner = (StartCommunication)activity;
}
else
throw new ClassCastException();
}
public void sendMessage()
{
mStartCommunicationListner.setComm(msg);
}
}
public class DisplayFragment extends Fragment
{
View mView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
mView = (View) inflater.inflate(R.layout.display_frgmt_layout, container);
return mView;
}
void setText(String msg)
{
TextView mTextView = (TextView) mView.findViewById(R.id.textView1);
mTextView.setText(msg);
}
}
我使用了这个链接来解决同样的问题,希望有人会发现它有用。非常简单和基础的例子。
http://infobloggall.com/2014/06/22/communication-between-activity-and-fragments/
我正在使用MainActivity的引用从FrgamentA触发接口的respond()方法。
接口communcator在fragmentA内定义,这是为了提供最少的访问权限给communicator接口。
以下是我的完整工作代码
FragmentA.java
public class FragmentA extends Fragment implements OnItemClickListener {
ListView list;
Communicator communicater;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.fragmenta, container,false);
}
public void setCommunicator(Communicator c){
communicater=c;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
communicater=(Communicator) getActivity();
list = (ListView) getActivity().findViewById(R.id.lvModularListView);
ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(getActivity(),
R.array.items, android.R.layout.simple_list_item_1);
list.setAdapter(adapter);
list.setOnItemClickListener(this);
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) {
communicater.respond(index);
}
public interface Communicator{
public void respond(int index);
}
}
fragmentB.java
public class FragmentA extends Fragment implements OnItemClickListener {
ListView list;
Communicator communicater;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.fragmenta, container,false);
}
public void setCommunicator(Communicator c){
communicater=c;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
communicater=(Communicator) getActivity();
list = (ListView) getActivity().findViewById(R.id.lvModularListView);
ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(getActivity(),
R.array.items, android.R.layout.simple_list_item_1);
list.setAdapter(adapter);
list.setOnItemClickListener(this);
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) {
communicater.respond(index);
}
public interface Communicator{
public void respond(int index);
}
}
MainActivity.java
public class MainActivity extends Activity implements FragmentA.Communicator {
FragmentManager manager=getFragmentManager();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentA fragA=(FragmentA) manager.findFragmentById(R.id.fragmenta);
fragA.setCommunicator(this);
}
@Override
public void respond(int i) {
// TODO Auto-generated method stub
FragmentB FragB=(FragmentB) manager.findFragmentById(R.id.fragmentb);
FragB.changetext(i);
}
}