내 프로그램에서 두 개의 fragmen간에 데이터를 전달하려고합니다. List에 저장되는 단순한 문자열입니다. 목록은 조각 A에서 공개되며 사용자가 목록 항목을 클릭하면 조각 B에 표시되어야합니다. 콘텐츠 제공자는 ID 만 지원하는 것 같아서 작동하지 않습니다. 어떤 제안?
답변:
번들을 사용하지 않으시겠습니까? 첫 번째 조각에서 설정하는 방법은 다음과 같습니다.
Fragment fragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putInt(key, value);
fragment.setArguments(bundle);
그런 다음 두 번째 Fragment에서 다음을 사용하여 데이터를 검색합니다.
Bundle bundle = this.getArguments();
int myInt = bundle.getInt(key, defaultValue);
번들에는 많은 데이터 유형에 대한 put 메소드가 있습니다. http://developer.android.com/reference/android/os/Bundle.html을 참조 하십시오.
Roboguice를 사용하는 경우 Roboguice의 EventManager를 사용하여 Activity를 인터페이스로 사용하지 않고도 데이터를 전달할 수 있습니다. 이것은 아주 깨끗한 IMO입니다.
Roboguice를 사용하지 않는 경우 Otto도 이벤트 버스로 사용할 수 있습니다. http://square.github.com/otto/
업데이트 20150909 : 이제 Green Robot Event Bus 또는 RxJava도 사용할 수 있습니다. 사용 사례에 따라 다릅니다.
로부터 Fragment 문서 :
예를 들어 사용자 이벤트를 기반으로 콘텐츠를 변경하기 위해 종종 하나의 Fragment가 다른 Fragment와 통신하기를 원할 것입니다. 모든 Fragment-to-Fragment 통신은 관련 활동을 통해 이루어집니다. 두 조각은 직접 통신해서는 안됩니다.
그래서 나는 당신이 문서 에서 기본적인 조각 훈련 문서 를 살펴 보길 권한다 . 예제와 둘러보기 가이드로 꽤 포괄적입니다.
따라서 Frag A와 Fragment B를 제어하는 Activity AB가 있다고 가정 해 보겠습니다. Fragment A 내부에는 Activity AB가 구현할 수있는 인터페이스가 필요합니다. 샘플 Android 코드에는 다음이 있습니다.
private Callbacks mCallbacks = sDummyCallbacks;
/ *이 조각을 포함하는 모든 활동이 구현해야하는 콜백 인터페이스. 이 메커니즘을 사용하면 활동에 항목 선택을 알릴 수 있습니다. * /
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 A라고 가정 해 보겠습니다). 이 콜백 인터페이스의 목적은 모든 활동이 구현할 수있는 Frag A 내부의 중첩 클래스와 같다고 생각합니다. 따라서 Fragment A가 TV 인 경우 CallBack은 Fragment A를 Activity AB에서 사용할 수있는 TV 리모컨 (인터페이스)입니다. 나는 멍청이이기 때문에 세부 사항에 대해 틀릴 수 있지만 프로그램이 모든 화면 크기에서 완벽하게 작동하도록 만들었으며 이것이 내가 사용한 것입니다.
따라서 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- 조각에서 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- 해당 이벤트를 구독하여 조각으로 받으십시오.
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(Message event){
mytextview.setText(event.message);
}
자세한 내용, 사용 사례 및 이벤트 버스 패턴에 대한 예제 프로젝트 .
제 경우에는 FragmentB-> FragmentA에서 데이터를 거꾸로 보내야 했으므로 조각이 이미 초기화되었으므로 Intents는 옵션이 아니 었 습니다. 위의 모든 답변이 좋게 들리지만 구현 하는 데 많은 보일러 플레이트 코드가 필요 하므로 LocalBroadcastManager 를 사용 하는 훨씬 더 간단한 접근 방식 을 사용 했습니다. 위에서 말한대로 정확하게 수행하지만 불쾌한 상용구 코드가 없습니다. 아래에 예가 나와 있습니다.
조각을 보내는 중 (조각 B)
public class FragmentB {
private void sendMessage() {
Intent intent = new Intent("custom-event-name");
intent.putExtra("message", "your message");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
수신 할 메시지 조각 (FRAGMENT A)
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);
조각 B에서는 다음과 같이 정의 된 메서드를 가질 수 있습니다.
public static void setmyText(final String string) {
myTextView.setText(string);
}
Fragment B에서 myTextView를 정적으로 설정하고 Fragment A에서 Fragment B 클래스를 올바르게 가져 오는 것을 잊지 마십시오.
최근에 내 프로젝트에서 절차를 수행했고 효과가있었습니다. 도움이 되었기를 바랍니다.
이 문서를 읽을 수 있습니다.이 개념은 http://developer.android.com/training/basics/fragments/communicating.html 여기에 잘 설명되어 있습니다.
비슷한 프로젝트를 진행 중이며 위의 상황에서 내 코드가 도움이 될 것 같습니다.
내가하는 일의 개요는 다음과 같습니다.
내 프로젝트에는 " FragmentA "및 "FragmentB " 라는 두 개의 조각이 있습니다 .
- FragmentA은 당신이 항목을 클릭 한 목록보기, 포함 FragmentA 에 전달이의 INDEX FragmentB 커뮤니케이터 인터페이스를 사용하여이
FrgamentA 에서 인터페이스의 respond () 메서드를 트리거 하고 있습니다.MainActivity의 참조를 사용하여 하고 있습니다.
Interface 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);
}
}
기본적으로 활동과 프래그먼트 간의 통신을위한 인터페이스를 구현합니다.
1) 주요 활동
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) 발신자 조각 (fragment-to-Activity)
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);
}
}
3) 수신자 조각 (Activity-to-fragment)
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/
조각 클래스 A
public class CountryListFragment extends ListFragment{
/** List of countries to be displayed in the ListFragment */
ListFragmentItemClickListener ifaceItemClickListener;
/** An interface for defining the callback method */
public interface ListFragmentItemClickListener {
/** This method will be invoked when an item in the ListFragment is clicked */
void onListFragmentItemClick(int position);
}
/** A callback function, executed when this fragment is attached to an activity */
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try{
/** This statement ensures that the hosting activity implements ListFragmentItemClickListener */
ifaceItemClickListener = (ListFragmentItemClickListener) activity;
}catch(Exception e){
Toast.makeText(activity.getBaseContext(), "Exception",Toast.LENGTH_SHORT).show();
}
}
조각 클래스 B
public class CountryDetailsFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/** Inflating the layout country_details_fragment_layout to the view object v */
View v = inflater.inflate(R.layout.country_details_fragment_layout, null);
/** Getting the textview object of the layout to set the details */
TextView tv = (TextView) v.findViewById(R.id.country_details);
/** Getting the bundle object passed from MainActivity ( in Landscape mode ) or from
* CountryDetailsActivity ( in Portrait Mode )
* */
Bundle b = getArguments();
/** Getting the clicked item's position and setting corresponding details in the textview of the detailed fragment */
tv.setText("Details of " + Country.name[b.getInt("position")]);
return v;
}
}
단편 간 데이터 전달을위한 기본 활동 클래스
public class MainActivity extends Activity implements ListFragmentItemClickListener {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
/** This method will be executed when the user clicks on an item in the listview */
@Override
public void onListFragmentItemClick(int position) {
/** Getting the orientation ( Landscape or Portrait ) of the screen */
int orientation = getResources().getConfiguration().orientation;
/** Landscape Mode */
if(orientation == Configuration.ORIENTATION_LANDSCAPE ){
/** Getting the fragment manager for fragment related operations */
FragmentManager fragmentManager = getFragmentManager();
/** Getting the fragmenttransaction object, which can be used to add, remove or replace a fragment */
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
/** Getting the existing detailed fragment object, if it already exists.
* The fragment object is retrieved by its tag name *
*/
Fragment prevFrag = fragmentManager.findFragmentByTag("in.wptrafficanalyzer.country.details");
/** Remove the existing detailed fragment object if it exists */
if(prevFrag!=null)
fragmentTransaction.remove(prevFrag);
/** Instantiating the fragment CountryDetailsFragment */
CountryDetailsFragment fragment = new CountryDetailsFragment();
/** Creating a bundle object to pass the data(the clicked item's position) from the activity to the fragment */
Bundle b = new Bundle();
/** Setting the data to the bundle object */
b.putInt("position", position);
/** Setting the bundle object to the fragment */
fragment.setArguments(b);
/** Adding the fragment to the fragment transaction */
fragmentTransaction.add(R.id.detail_fragment_container, fragment,"in.wptrafficanalyzer.country.details");
/** Adding this transaction to backstack */
fragmentTransaction.addToBackStack(null);
/** Making this transaction in effect */
fragmentTransaction.commit();
}else{ /** Portrait Mode or Square mode */
/** Creating an intent object to start the CountryDetailsActivity */
Intent intent = new Intent("in.wptrafficanalyzer.CountryDetailsActivity");
/** Setting data ( the clicked item's position ) to this intent */
intent.putExtra("position", position);
/** Starting the activity by passing the implicit intent */
startActivity(intent);
}
}
}
Detailde 활동 수업
public class CountryDetailsActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/** Setting the layout for this activity */
setContentView(R.layout.country_details_activity_layout);
/** Getting the fragment manager for fragment related operations */
FragmentManager fragmentManager = getFragmentManager();
/** Getting the fragmenttransaction object, which can be used to add, remove or replace a fragment */
FragmentTransaction fragmentTransacton = fragmentManager.beginTransaction();
/** Instantiating the fragment CountryDetailsFragment */
CountryDetailsFragment detailsFragment = new CountryDetailsFragment();
/** Creating a bundle object to pass the data(the clicked item's position) from the activity to the fragment */
Bundle b = new Bundle();
/** Setting the data to the bundle object from the Intent*/
b.putInt("position", getIntent().getIntExtra("position", 0));
/** Setting the bundle object to the fragment */
detailsFragment.setArguments(b);
/** Adding the fragment to the fragment transaction */
fragmentTransacton.add(R.id.country_details_fragment_container, detailsFragment);
/** Making this transaction in effect */
fragmentTransacton.commit();
}
}
연속 배열
public class Country {
/** Array of countries used to display in CountryListFragment */
static String name[] = new String[] {
"India",
"Pakistan",
"Sri Lanka",
"China",
"Bangladesh",
"Nepal",
"Afghanistan",
"North Korea",
"South Korea",
"Japan",
"Bhutan"
};
}
자세한 내용은이 링크 [ http://wptrafficanalyzer.in/blog/itemclick-handler-for-listfragment-in-android/]를 방문 하세요 . 전체 예가 있습니다 ..
getParentFragmentManager().setFragmentResultListener이것이 2020 년 방식입니다. 유일한 제한은 번들을 사용하여 데이터를 전달하는 것입니다. 문서 확인자세한 정보와 예제 를 .
다른 방법
getActivity()프래그먼트 간의 공유 활동을 하고 캐스트 한 다음 데이터를 전달하는 브리지로 사용합니다. 이 솔루션은 활동과 조각 사이에 필요한 큐 펠링 때문에 권장되지 않지만 KitKat 시대에이 작업을 수행하는 인기있는 방법이었습니다 ...FragmentManager은 번들에만 국한되지 않는다는 것입니다. 그러나 단점은 활동 라이프 사이클을 엉망으로 IllegalStateException만들고 조각 관리자가 저장 상태에 있거나 활동이 파괴되었을 때 와 같은 예외가 발생하는 엣지 케이스 버그가 발생할 수 있다는 것 입니다. 또한 크로스 프로세싱 통신을 지원하지 않습니다.기본적으로 여기서는 Fragment 간의 통신을 다루고 있습니다. 프래그먼트 간의 통신은 절대로 직접 가능하지 않습니다. 두 조각이 모두 생성되는 컨텍스트에서의 활동이 포함됩니다.
보내는 프래그먼트에 인터페이스를 만들고 메시지를 재 보유하고 수신 프래그먼트로 전송할 활동에 인터페이스를 구현해야합니다.