2014-06-06 3 views
0

EDIT :이 질문은 Android 애플리케이션 개발을 시작할 때 첫 번째 Android 프로젝트 중 하나의 일부로 작성되었습니다. 나는 이것을 역사적인 이유로 보존하고 있지만 대신 EventBus 나 RxJava를 사용하는 것을 고려해야한다. 이것은 거대한 혼란입니다.LocalBroadcastManager를 사용하여 Fragment에서 Activity로 통신

이것을 사용하지 마십시오. 고맙습니다.

여러 개의 "조각"이있는 단일 활동을 사용하는 문제를 해결하려면 멋진 모습을 원한다면 flowless을 사용자 정의보기 그룹과 함께 사용하십시오.


나는 인스턴스화 어떤 조각 활동을 이야기하는 LocalBroadcastManager를 통해 방송 의도를 사용하여 조각에서, 파편의 생성을 시작하는 방법을 구현했습니다.

나는 이것이 매우 길다는 것을 알고 있지만 디버깅을 요구하지는 않는다. 의도 한대로 완벽하게 작동한다. 데이터가 수신되고, 생성물이 번들로 매개 변수화 될 수 있으며, 단편은 직접적으로 생성되지 않는다. 다른 프래그먼트를 인스턴스화합니다.

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

이 방법을 다음과 같이 외모를 생성하는 조각 :

메시지를 처리 ​​할 수있는 초기 컨테이너 활동은 다음과 같습니다
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]; 
     } 
    }; 
} 
} 

:

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

을 그리고 조각 " 다음과 같이 다른 단편을 인스턴스화하십시오 :

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

그리고 컨테이너 활동 인스턴스화 요청 수신 :

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

내 질문은,이 사실은 좋은 생각, 또는이 "오버 엔지니어링"의 끔찍한 경우 (각 조각을위한 공장을 작성하고 전송입니다 그것은 가능한 가장 홀더 활동의 인터페이스의 활동을 캐스팅하지 않고 그와 같은 기능을 호출하는 것보다는 로컬 방송의 형태로 활동에?

내 목표는 이런 방식으로 "지점"조각을 보유하는 데 동일한 활동을 사용할 수 있으므로 각 메뉴 지점마다 하나씩 만들 필요가 없습니다. 단순히 동일한 활동을 다시 사용하지 말고 모든 논리를 조각으로 나눕니다. (현재 오리엔테이션 기반의 레이아웃 구성을 지원하지 않는다. 그 단점을 보게된다. 그리고 각 단편은 정적 인 작성자를 필요로한다. 이것은 보일러 플레이트 코드이다.)

로컬 브로드 캐스트 관리자를 사용해서는 안되는 이유를 알고 계시다면 언제든지 응답을 들으실 수 있습니다. 나는 그것이 꽤 깔끔하다고 생각하지만, 단순한 것을 단순하게 복잡하게 만들 가능성이있다.

+0

는 u는 간단한 콜백 방법을 사용할 수 있습니다, 그것보다 깨끗하고 간단한 방법 – r4jiv007

+0

당신이 그것을에 대한 예제 코드 또는 링크를 제공 할 수 있습니다 : 당신은 다음과 같은 사용을 통해 활동-조각 또는 조각 - 조각 사이의 통신을 구현할 수있다? 현재 '((ShowDialog) this.getActivity())와 같은 라인으로 시작했습니다. showDialog (new EditNameDialog.Creator());' 하지만 심지어 그 창조자를 사용합니다. 제 목표는 여러 단편간에 동일한 '컨테이너'활동을 재사용 할 수 있도록하여 각 하위 메뉴에 대한 활동을 할 필요가 없도록하는 것이 었습니다. – EpicPandaForce

+0

http://developer.android.com/training/basics/fragments/communicating.html – r4jiv007

답변

1

당신은 다시 가용성을 유지 조각의 그것 때문에 주요 목적을 위해 인터페이스를 사용할 수 있습니다

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

이 링크 조각에서

#.

enter image description here

+0

프래그먼트가 의사 소통 할 필요가 없다는 사실을 감안할 때 내 솔루션이 '괜찮 았을'것이라고 생각했지만, 그렇게했다면 실패 할 것이고 추가 합병증이 추가됩니다. 이 방법을 제대로 사용하면 도움이되는 좋은 해결책입니다. 감사합니다. – EpicPandaForce

+3

좋은 설명 ..이 스크린 샷은 Slidenerd 비디오 시리즈에서 가져온 것입니다. 제가 조각 통신을 위해 본 awsome 설명 중 하나입니다. –

+0

감사합니다. 비슷한 샘플 응용 프로그램을 여기에 있습니다. http://wiki.workassis.com/android-fragment-communication/ –

2

귀하의 moto가 입니다. 그 활동 및 다른 단편과 의사 소통하기위한 단편. 이 경우 해당 사항을 확인하십시오.

Fragment가 해당 Activity까지 통신 할 수있게하려면 Fragment 클래스에서 인터페이스를 정의하고 Activity 내에서 구현할 수 있습니다. Fragment는 onAttach() 라이프 사이클 메소드에서 인터페이스 구현을 캡처 한 다음 Activity와 통신하기 위해 Interface 메소드를 호출 할 수 있습니다.

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

+0

위대한 링크. 궁금한 Iam 이유는 그것을 일찍 발견하지 못했습니다. – JacksOnF1re

관련 문제