결과에 대한 시작 조각처럼 작동하는 방법이 있습니까?
현재 오버레이에 조각이 있습니다. 서비스에 로그인하기위한 것입니다. 전화 앱에서 오버레이에 표시하려는 각 단계는 자체 화면과 활동입니다. 로그인 프로세스에는 세 부분이 있으며 각 부분에는 startActivityForResult ()로 호출 된 자체 활동이 있습니다.
이제 조각과 오버레이를 사용하여 동일한 작업을 수행하고 싶습니다. 오버레이는 각 활동에 해당하는 조각을 표시합니다. 문제는 이러한 조각이 Honeycomb API의 활동에서 호스팅된다는 것입니다. 첫 번째 조각이 작동하도록 할 수 있지만 startActivityForResult ()가 필요하지만 불가능합니다. startFragmentForResult () 줄을 따라 새 조각을 시작할 수 있고 완료되면 이전 조각에 결과를 반환 할 수있는 것이 있습니까?
모든 조각은 활동 내에 있습니다. 결과에 대한 조각을 시작하는 것은 그다지 의미가 없습니다. 왜냐하면 그것을 수용하는 활동은 항상 그것에 접근 할 수 있고 그 반대도 마찬가지이기 때문입니다. 조각이 결과를 전달해야하는 경우 해당 활동에 액세스하여 결과를 설정하고 완료 할 수 있습니다. 단일 활동에서 프래그먼트를 교환하는 경우에도 두 프래그먼트 모두에서 활동에 계속 액세스 할 수 있으며 모든 메시지 전달은 단순히 활동을 통과 할 수 있습니다.
프래그먼트와 액티비티 사이에는 항상 커뮤니케이션이 있다는 것을 기억하십시오. 결과를 시작하고 끝내는 것은 활동 간의 통신 메커니즘입니다. 활동은 필요한 정보를 프래그먼트에 위임 할 수 있습니다.
원한다면 Fragment 간의 통신을위한 몇 가지 방법이 있습니다.
setTargetFragment(Fragment fragment, int requestCode)
getTargetFragment()
getTargetRequestCode()
이것을 사용하여 콜백 할 수 있습니다.
Fragment invoker = getTargetFragment();
if(invoker != null) {
invoker.callPublicMethod();
}
내 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;
}
}
프래그먼트간에 동일한 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(this).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(this).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"
}
}
조각에서 getActivity ()를 호출 할 수 있습니다. 이렇게하면 조각을 만든 활동에 액세스 할 수 있습니다. 여기에서 사용자 정의 메소드를 호출하여 값을 설정하거나 값을 전달할 수 있습니다.
There is an Android library - FlowR that allows you to start fragments for results.
Starting a fragment for result.
Flowr.open(RequestFragment.class)
.displayFragmentForResults(getFragmentId(), REQUEST_CODE);
Handling results in the calling fragment.
@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");
}
}
}
Setting the result in the Fragment.
Flowr.closeWithResults(getResultsResponse(resultCode, resultData));
You can use EventBus. It simplifies communication between Activities, Fragments, Threads, Services, etc. Less code, better quality.
The easiest way to pass data back is by setArgument(). For example, you have fragment1 which calls fragment2 which calls fragment3, fragment1 -> framgnet2 -> fargment3
In fragment1
public void navigateToFragment2() {
if (fragmentManager == null) return;
Fragment2 fragment = Fragment2.newInstance();
String tag = "Fragment 2 here";
fragmentManager.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.add(R.id.flContent, fragment, tag)
.addToBackStack(null)
.commitAllowingStateLoss();
}
In fragment2 we call fragment3 as usual
private void navigateToFragment3() {
if (fragmentManager == null) return;
Fragment3 fragment = new Fragment3();
fragmentManager.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(R.id.flContent, fragment, tag)
.addToBackStack(null)
.commit();
}
When we finished our task in fragment3 now we call like this:
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
if (fragmentManager == null) return;
fragmentManager.popBackStack();
Bundle bundle = new Bundle();
bundle.putString("bundle_filter", "data");
fragmentManager.findFragmentByTag("Fragment 2 here").setArguments(bundle);
Now in fragment2 we can easily call arguments
@Override
public void onResume() {
super.onResume();
Bundle rgs = getArguments();
if (args != null)
String data = rgs.getString("bundle_filter");
}
A solution using interfaces (and Kotlin). The core idea is to define a callback interface, implement it in your activity, then call it from your fragment.
First, create an interface ActionHandler
:
interface ActionHandler {
fun handleAction(actionCode: String, result: Int)
}
Next, call this from your child (in this case, your fragment):
companion object {
const val FRAGMENT_A_CLOSED = "com.example.fragment_a_closed"
}
fun closeFragment() {
try {
(activity as ActionHandler).handleAction(FRAGMENT_A_CLOSED, 1234)
} catch (e: ClassCastException) {
Timber.e("Calling activity can't get callback!")
}
dismiss()
}
Finally, implement this in your parent to receive the callback (in this case, your Activity):
class MainActivity: ActionHandler {
override fun handleAction(actionCode: String, result: Int) {
when {
actionCode == FragmentA.FRAGMENT_A_CLOSED -> {
doSomething(result)
}
actionCode == FragmentB.FRAGMENT_B_CLOSED -> {
doSomethingElse(result)
}
actionCode == FragmentC.FRAGMENT_C_CLOSED -> {
doAnotherThing(result)
}
}
}
Another thing you could do depending on your architecture is use a shared ViewModel between the fragments. So in my case FragmentA is a form, and FragmentB is a item selection view where the user can search and select an item, storing it in the ViewModel. Then when I come back to FragmentA, the information is already stored !
'program tip' 카테고리의 다른 글
postgreSQL-psql \ i : 주어진 경로에서 스크립트를 실행하는 방법 (0) | 2020.10.17 |
---|---|
파일 설명자에서 FILE 포인터를 얻는 방법은 무엇입니까? (0) | 2020.10.17 |
Scalaz 상태 모나드 예제 (0) | 2020.10.17 |
변수가 Moment.js 객체인지 테스트하는 방법은 무엇입니까? (0) | 2020.10.17 |
새 프로젝트는 log4j 대신 logback을 사용해야합니까? (0) | 2020.10.17 |