[android] 결과에 대한 시작 조각처럼 작동하는 방법이 있습니까?

현재 오버레이에 조각이 있습니다. 서비스에 로그인하기위한 것입니다. 전화 앱에서 오버레이에 표시하려는 각 단계는 자체 화면과 활동입니다. 로그인 프로세스에는 세 부분이 있으며 각 부분에는 startActivityForResult ()로 호출 된 자체 활동이 있습니다.

이제 조각과 오버레이를 사용하여 동일한 작업을 수행하고 싶습니다. 오버레이는 각 활동에 해당하는 조각을 표시합니다. 문제는 이러한 프래그먼트가 Honeycomb API의 활동에서 호스팅된다는 것입니다. 첫 번째 조각이 작동하도록 할 수는 있지만 가능하지 않은 startActivityForResult ()가 필요합니다. startFragmentForResult () 줄을 따라 새 조각을 시작할 수 있고 완료되면 이전 조각에 결과를 반환 할 수있는 것이 있습니까?



답변

모든 조각은 활동 내에 있습니다. 결과에 대한 조각을 시작하는 것은 그다지 의미가 없습니다. 왜냐하면 그것을 수용하는 활동은 항상 그것에 접근 할 수 있고 그 반대도 마찬가지이기 때문입니다. Fragment가 결과를 전달해야하는 경우 활동에 액세스하여 결과를 설정하고 완료 할 수 있습니다. 단일 활동에서 프래그먼트를 교환하는 경우에도 두 프래그먼트 모두에서 활동에 계속 액세스 할 수 있으며 모든 메시지 전달은 단순히 활동을 통과 할 수 있습니다.

프래그먼트와 액티비티간에 항상 커뮤니케이션이 있다는 것을 기억하십시오. 결과를 시작하고 끝내는 것은 활동 간의 통신 메커니즘입니다. 활동은 필요한 정보를 프래그먼트에 위임 할 수 있습니다.


답변

원한다면 Fragment 간의 통신을위한 몇 가지 방법이 있습니다.

setTargetFragment(Fragment fragment, int requestCode)
getTargetFragment()
getTargetRequestCode()

이것을 사용하여 콜백 할 수 있습니다.

Fragment invoker = getTargetFragment();
if(invoker != null) {
    invoker.callPublicMethod();
}


답변

프래그먼트간에 동일한 ViewModel을 공유 할 수 있습니다

SharedViewModel

import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel

class SharedViewModel : ViewModel() {

    val stringData: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

}

FirstFragment

import android.arch.lifecycle.Observer
import android.os.Bundle
import android.arch.lifecycle.ViewModelProviders
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

class FirstFragment : Fragment() {

    private lateinit var sharedViewModel: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        activity?.run {
            sharedViewModel = ViewModelProviders.of(activity).get(SharedViewModel::class.java)
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_first, container, false)
    }

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

        sharedViewModel.stringData.observe(this, Observer { dateString ->
            // get the changed String
        })

    }

}

SecondFragment

import android.arch.lifecycle.ViewModelProviders
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGrou

class SecondFragment : Fragment() {

    private lateinit var sharedViewModel: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        activity?.run {
            sharedViewModel = ViewModelProviders.of(activity).get(SharedViewModel::class.java)
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_first, container, false)
    }

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

    private fun changeString() {
        sharedViewModel.stringData.value = "Test"
    }

}


답변

최근 구글은 단지에 새로운 기능을 추가했습니다 FragmentManager(가) 만든 FragmentManager조각 결과를위한 중앙 저장소 역할을 할 수 있습니다. Fragment간에 데이터를 쉽게주고받을 수 있습니다.

조각을 시작합니다.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Use the Kotlin extension in the fragment-ktx artifact
    setResultListener("requestKey") { key, bundle ->
        // We use a String here, but any type that can be put in a Bundle is supported
        val result = bundle.getString("bundleKey")
        // Do something with the result...
    }
}

결과를 되돌리려는 Fragment.

button.setOnClickListener {
    val result = "result"
    // Use the Kotlin extension in the fragment-ktx artifact
    setResult("requestKey", bundleOf("bundleKey" to result))
}

스 니펫은 Google의 공식 문서에서 가져온 것입니다.
https://developer.android.com/training/basics/fragments/pass-data-between#kotlin

작성된이 답변의 데이터에서이 기능은 여전히 alpha상태입니다. 이 종속성을 사용하여 시도해 볼 수 있습니다.

androidx.fragment:fragment:1.3.0-alpha05


답변

내 2 센트.

숨기기 및 표시 / 추가 (기존 / 신규)를 사용하여 이전 조각을 새 조각으로 교체하여 조각간에 전환합니다. 그래서이 대답은 나처럼 조각을 사용하는 개발자를위한 것입니다.

그런 다음 onHiddenChanged방법을 사용하여 이전 조각이 새 조각에서 다시 전환되었음을 알 수 있습니다. 아래 코드를 참조하십시오.

새 조각을 떠나기 전에 이전 조각에서 쿼리 할 전역 매개 변수에 결과를 설정했습니다. 이것은 매우 순진한 솔루션입니다.

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
    if (hidden) return;
    Result result = Result.getAndReset();
    if (result == Result.Refresh) {
        refresh();
    }
}

public enum Result {
    Refresh;

    private static Result RESULT;

    public static void set(Result result) {
        if (RESULT == Refresh) {
            // Refresh already requested - no point in setting anything else;
            return;
        }
        RESULT = result;
    }

    public static Result getAndReset() {
        Result result = RESULT;
        RESULT = null;
        return result;
    }
}


답변

조각에서 getActivity ()를 호출 할 수 있습니다. 이렇게하면 조각을 만든 활동에 액세스 할 수 있습니다. 여기에서 사용자 정의 메소드를 호출하여 값을 설정하거나 값을 전달할 수 있습니다.


답변

결과에 대한 조각을 시작할 수 있는 Android 라이브러리 -FlowR 이 있습니다.

결과에 대한 조각을 시작합니다.

Flowr.open(RequestFragment.class)
    .displayFragmentForResults(getFragmentId(), REQUEST_CODE);

호출 조각에서 결과를 처리합니다.

@Override
protected void onFragmentResults(int requestCode, int resultCode, Bundle data) {
    super.onFragmentResults(requestCode, resultCode, data);

    if (requestCode == REQUEST_CODE) {
        if (resultCode == Activity.RESULT_OK) {
            demoTextView.setText("Result OK");
        } else {
            demoTextView.setText("Result CANCELED");
        }
    }
}

조각에 결과를 설정합니다.

Flowr.closeWithResults(getResultsResponse(resultCode, resultData));