Show DialogFragment from onActivityResult

前端 未结 17 1189
傲寒
傲寒 2020-12-04 06:47

I have the following code in my onActivityResult for a fragment of mine:

onActivityResult(int requestCode, int resultCode, Intent data){
   //other code
   P         


        
相关标签:
17条回答
  • 2020-12-04 06:49

    I know this was answered quite a while ago.. but there is a much easier way to do this than some of the other answers I saw on here... In my specific case I needed to show a DialogFragment from a fragments onActivityResult() method.

    This is my code for handling that, and it works beautifully:

    DialogFragment myFrag; //Don't forget to instantiate this
    FragmentTransaction trans = getActivity().getSupportFragmentManager().beginTransaction();
    trans.add(myFrag, "MyDialogFragmentTag");
    trans.commitAllowingStateLoss();
    

    As was mentioned in some of the other posts, committing with state loss can cause problems if you aren't careful... in my case I was simply displaying an error message to the user with a button to close the dialog, so if the state of that is lost it isn't a big deal.

    Hope this helps...

    0 讨论(0)
  • 2020-12-04 06:50

    The comment left by @Natix is a quick one-liner that some people may have removed.

    The simplest solution to this problem is to call super.onActivityResult() BEFORE running your own code. This works regardless if you're using the support library or not and maintains behavioural consistency in your Activity.

    There is:

    • No need to add faux delays using threads, handlers or sleeps.
    • No need to commit allowing state loss or subclass to override show(). It is NOT a bug, it's a warning. Don't throw away state data. (Another one, bonus example)
    • No need to keep track of dialog fragments in your activity (hello memory leaks!)
    • And by God, no need to mess around with the activity lifecycle by calling onStart() manually.

    The more I read into this the more insane hacks I've seen.

    If you're still running into issues, then the one by Alex Lockwood is the one to check.

    • No need to write any code for onSaveInstanceState() (Another one)
    0 讨论(0)
  • 2020-12-04 06:51

    EDIT: Not a bug, but more of a deficiency in the fragments framework. The better answer to this question is the one provided by @Arcao above.

    ---- Original post ----

    Actually it's a known bug with the support package (edit: not actually a bug. see @alex-lockwood's comment). A posted work around in the comments of the bug report is to modify the source of the DialogFragment like so:

    public int show(FragmentTransaction transaction, String tag) {
        return show(transaction, tag, false);
    }
    
    
    public int show(FragmentTransaction transaction, String tag, boolean allowStateLoss) {
        transaction.add(this, tag);
        mRemoved = false;
        mBackStackId = allowStateLoss ? transaction.commitAllowingStateLoss() : transaction.commit();
        return mBackStackId;
    }
    

    Note this is a giant hack. The way I actually did it was just make my own dialog fragment that I could register with from the original fragment. When that other dialog fragment did things (like be dismissed), it told any listeners that it was going away. I did it like this:

    public static class PlayerPasswordFragment extends DialogFragment{
    
     Player toJoin;
     EditText passwordEdit;
     Button okButton;
     PlayerListFragment playerListFragment = null;
    
     public void onCreate(Bundle icicle){
       super.onCreate(icicle);
       toJoin = Player.unbundle(getArguments());
       Log.d(TAG, "Player id in PasswordFragment: " + toJoin.getId());
     }
    
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle){
         View v = inflater.inflate(R.layout.player_password, container, false);
         passwordEdit = (EditText)v.findViewById(R.id.player_password_edit);
         okButton = (Button)v.findViewById(R.id.ok_button);
         okButton.setOnClickListener(new View.OnClickListener(){
           public void onClick(View v){
             passwordEntered();
           }
         });
         getDialog().setTitle(R.string.password_required);
         return v;
     }
    
     public void passwordEntered(){
       //TODO handle if they didn't type anything in
       playerListFragment.joinPlayer(toJoin, passwordEdit.getText().toString());
       dismiss();
     }
    
     public void registerPasswordEnteredListener(PlayerListFragment playerListFragment){
       this.playerListFragment = playerListFragment;
     }
    
     public void unregisterPasswordEnteredListener(){
       this.playerListFragment = null;
     }
    }
    

    So now I have a way to notify the PlayerListFragment when things happen. Note that its very important that you call unregisterPasswordEnteredListener appropriately (in the above case when ever the PlayerListFragment "goes away") otherwise this dialog fragment might try to call functions on the registered listener when that listener doesn't exist any more.

    0 讨论(0)
  • 2020-12-04 06:55

    You cannot show dialog after attached activity called its method onSaveInstanceState(). Obviously, onSaveInstanceState() is called before onActivityResult(). So you should show your dialog in this callback method OnResumeFragment(), you do not need to override DialogFragment's show() method. Hope this will help you.

    0 讨论(0)
  • 2020-12-04 06:55

    The cleanest solution I found is this:

    @Override
    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                onActivityResultDelayed(requestCode, resultCode, data);
            }
        });
    }
    
    public void onActivityResultDelayed(int requestCode, int resultCode, Intent data) {
        // Move your onActivityResult() code here.
    }
    
    0 讨论(0)
  • 2020-12-04 06:57

    As you all know this problem is because of on onActivityResult() is calling before onstart(),so just call onstart() at start in onActivityResult() like i have done in this code

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
          onStart();
          //write you code here
    }
    
    0 讨论(0)
提交回复
热议问题