programing

XML 레이아웃에서 조각을 선언하는 경우 번들을 전달하려면 어떻게 해야 합니까?

magicmemo 2023. 9. 13. 22:32
반응형

XML 레이아웃에서 조각을 선언하는 경우 번들을 전달하려면 어떻게 해야 합니까?

파편으로 대체한 활동이 있어요활동은 활동이 어떤 데이터를 표시해야 하는지에 대한 추가 정보가 있는 의도를 취했습니다.

내 활동은 동일한 작업을 수행하는 조각 주위의 포장지에 불과하므로 태그와 함께 XML로 조각을 선언하면 번들을 어떻게 조각으로 가져올 수 있습니까?

FragmentTransaction을 사용하여 Fragment를 ViewGroup에 넣는다면 Fragment 생성기에서 이 정보를 전달할 기회가 있겠지만, Fragment가 XML에 정의되어 있는 상황이 궁금합니다.

내 활동은 동일한 작업을 수행하는 조각 주위의 포장지에 불과하므로 태그와 함께 XML로 조각을 선언하면 번들을 어떻게 조각으로 가져올 수 있습니까?

그럴수는 없어요.

ㅇ, ㅇㅇ로 .findFragmentById()에에FragmentManager인플레 이후의 프래그먼트를 검색한 다음 프래그먼트에 대한 메소드를 호출하여 데이터를 연관시킵니다.그것은 분명히 있을 수 없지만,setArguments()를 구성 할 수 (, 의 으로 를 하도록 할 은 할 하도록 ( )onSaveInstanceState(),setRetainInstance(true) ).

캡슐화된 방식은 아니지만, 상위 활동에서 번들을 "풀어"냈습니다.

Bundle bundle = getActivity().getIntent().getExtras();

번들을 전달할 수는 없지만 XML을 통해 매개 변수(또는 속성)를 전달할 수는 있습니다.

이 프로세스는 View 사용자 지정 특성을 정의하는 방법과 유사합니다.Android Studio(현재)를 제외하고는 프로세스에 도움이 되지 않습니다.

이것이 인수를 사용하는 당신의 프래그먼트라고 가정합니다. (코틀린을 사용하겠지만 자바에서도 완전히 작동합니다.)

class MyFragment: Fragment() {

    // your fragment parameter, a string
    private var screenName: String? = null

    override fun onAttach(context: Context?) {
        super.onAttach(context)
        if (screenName == null) {
            screenName = arguments?.getString("screen_name")
        }
    }
}

그리고 당신은 다음과 같은 일을 하고 싶어합니다.

<fragment
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/myFragment"
    android:name="com.example.MyFragment"
    app:screen_name="@string/screen_a"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

를 합니다.app:screen_name="@string/screen_a"

만 하면 (하려면 에 만 을 만 하려면 ( )fragment_attrs.xml또는 원하는 이름을 선택하십시오.):

<!-- define your attribute name and type -->
<attr name="screen_name" format="string|reference"/>

<!-- define a bunch of constants you wanna use -->
<string name="screen_a" translatable="false">ScreenA</string>
<string name="screen_b" translatable="false">ScreeenB</string>

<!-- now define which arguments your fragment is gonna have (can be more then one) -->
<!-- the convention is "FragmentClassName_MembersInjector" -->
<declare-styleable name="MyFragment_MembersInjector">
    <attr name="screen_name"/>
</declare-styleable>

거의 완료되었습니다. 단편에서 읽기만 하면 되므로 메소드를 추가합니다.

override fun onInflate(context: Context?, attrs: AttributeSet?, savedInstanceState: Bundle?) {
    super.onInflate(context, attrs, savedInstanceState)
    if (context != null && attrs != null && screenName == null) {
        val ta = context.obtainStyledAttributes(attrs, R.styleable.MyFragment_MembersInjector)
        if (ta.hasValue(R.styleable.MyFragment_MembersInjector_screen_name)) {
            screenName = ta.getString(R.styleable.MyFragment_MembersInjector_screen_name)
        }
        ta.recycle()
    }
}

et voila, 조각에 XML 속성 포함 :)

제한 사항:

  • Android Studio는 레이아웃 XML에서 이러한 인수를 자동으로 완료하지 않습니다.
  • 당신은 통과할 수 없습니다.Parcelable 로 할 수 합니다.

또 다른 옵션은 XML에 fragment를 선언하지 않는 것입니다. 정확히 당신이 원하는 것이 아니라는 것을 압니다.그러나 보기에서 다음과 같이 간단한 레이아웃을 선언할 수 있습니다.

    <LinearLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" />

다음엔 당신의 Activity클래스는 조각으로 레이아웃을 프로그램적으로 부풀립니다.이렇게 하면 args를 사용하여 매개변수를 전달할 수 있습니다.

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MyFragment fragment = MyFragment.newInstance();
Bundle args = new Bundle();
args.putInt(Global.INTENT_INT_ROLE, 1);
fragment.setArguments(args);
fragmentTransaction.add(R.id.fragment_container, fragment, "MyActivity");
fragmentTransaction.commit();

그 조각에서,

if (getArguments() != null) {
   int role = getArguments().getInt(Global.INTENT_INT_ROLE); }

이 접근법은 xml에 선언하는 것만큼 깨끗하고 간단하지는 않지만 프래그먼트에 대한 통제력이 훨씬 더 높아지기 때문에 이동했습니다.

너무 늦은 답변인건 알지만 누군가가 필요할거 같아요 :)

override onAttachFragment()

@Override
public void onAttachFragment(Fragment fragment)
{
    super.onAttachFragment(fragment);

    if (fragment.getId() == R.id.frgBlank)
    {
        Bundle b = new Bundle();
        b.putString("msg", "Message");

        fragment.setArguments(b);
    }
}

CreateView 메서드의 조각에 표시됩니다.

Bundle b = getArguments();
if (b != null)
{
    Toast.makeText(getBaseContext(), b.getString("msg"), Toast.LENGTH_SHORT).show();
}

제가 볼 수 있는 유일한 해결책은 인수를 데이터 교환 채널로 사용하지 않는 것입니다.대신 다른 곳에서 필요한 정보를 얻기 위해 조각을 만듭니다.다시 전화를 걸어 적절한 활동을 얻고 임시 저장 메모리, 싱글톤 개체 등을 확인합니다.

도움이 될 수 있는 또 다른 해결책은 Otto와 같이 Mediator 디자인 패턴을 통해 관련 없는 개체가 메시지를 교환할 수 있는 프레임워크를 사용하는 것입니다.

이 방법은 저에게 효과가 있었습니다.

Anywhere에서 온 번들을 전달하지 않고 대신 조각 자체에서 onAttach 메서드에서 인수를 설정할 수 있습니다.

프래그먼트의 라이프사이클 메소드 나중에 번들 인수를 사용할 수 있습니다.

override fun onAttach(context: Context) {
        super.onAttach(context)
        if(arguments == null){
            val bundle = Bundle()
            bundle.putString("mykey", "myvalue")
            arguments = bundle
        }
    }

누구나 사용 가능한 장소에서 값을 직접 사용할 수 있는데 왜 프래그먼트에 인수를 설정해야 하는지 질문할 수 있습니다.맞는 말이지만, 이 방법은 다른 클래스에 이러한 주장을 전달할 때도 사용할 수 있습니다. 예를 들어 어떤 보기 모델이든 말이죠.

예를들면

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        /*
         Here I am passing these arguments to a viewmodel 
        */
        viewModel.prepareData(arguments) 
        
        --------
        --------
        --------

    }

감사해요.

Androidx.fragment 모듈의 v1.3.0(2021년 2월) 이후로, 그들은 더 이상 사용하지 않습니다.onAttachFragment()FragmentManager에 첨부된 FragmentOnAttachListener를 사용하는 것을 선호하여 콜백합니다.그래서 너의 안에FragmentActivityonCreate, 당신은 다음과 같은 것을 할 수 있습니다.

getSupportFragmentManager().addFragmentOnAttachListener((fragmentManager, fragment) -> {
    if (fragment instanceof MyFragment) {
        Bundle args = getIntent().getExtras();
        fragment.setArguments(args);
    }
}

다음에 불이 붙습니다.setContentView()사용하는 경우<fragment>당신의 XML에서, 그러나 만약 당신이 a를 사용했다면 나중에 발생합니다.<FragmentContainerView>.

구성 변경으로 인해 기존의 조각이 내부에 다시 부착될 수 있으므로 주의해야 합니다.super.onCreate, 따라서 이 시점 전에 청취자를 추가할 필요가 있었습니다. (그렇기는 하지만 통과를 위해서는 필요하지 않습니다.Bundleargs, 그렇지 않으면 SaveInstanceState()에서 먼저 사용을 시도해야 합니다.)


덧붙여서 "onAttach"를 듣는 것도 필요한 경우 프래그먼트 보기 라이프사이클의 관찰자를 추가할 수 있는 편리한 장소가 될 수 있습니다. 프래그먼트 보기가 인스턴스화된 후 액티비티에서 작업을 수행해야 하는 경우 예를 들어 다음을 추가합니다.

        LiveData<LifecycleOwner> liveData = fragment.getViewLifecycleOwnerLiveData();
        // Let this observer be constrained to the fragment's lifecycle.
        liveData.observe(fragment, new Observer<LifecycleOwner>() {
            @Override
            public void onChanged(LifecycleOwner lifecycleOwner) {
                // ...do work...
                // If you don't need to listen anymore, can clean ourselves up early.
                liveData.removeObserver(this);
            }
        });

또는 Activity에서 Fragment의 보기 라이프사이클을 관찰하는 대신(ActivityCreated()) Fragment에서 Activity의 Lifecycle을 관찰하는 대신, Fragment에서 Activity의 Lifecycle을 들을 수도 있습니다!첨부(context) 콜백에 있는 Fragments에서 Create(@NonNull LifecycleOwner)에 구현하는 자신의 관찰자를 추가합니다.re: onActivityCreated가 더 이상 사용되지 않습니다. LifecycleOver를 제대로 사용하는 방법은 무엇입니까?

언급URL : https://stackoverflow.com/questions/13034746/if-i-declare-a-fragment-in-an-xml-layout-how-do-i-pass-it-a-bundle

반응형