从自定义 Fragment 调用 DialogFragment,然后设置其 属性

Call DialogFragment from a custom Fragment, then set its property

成功遵循指南后Accessing Google APIs, I am trying to move all the Google+ related code from my MainActivity to a separate custom GoogleFragment

但是我被困在最后一个地方 - 在我的自定义片段中,我不知道如何在 DialogFragment 被关闭后访问 mResolvingError 字段:

public class GoogleFragment extends Fragment
        implements GoogleApiClient.OnConnectionFailedListener {

    private boolean mResolvingError = false; // HOW TO ACCESS?

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        if (mResolvingError) {
            // Already attempting to resolve an error.
            return;
        } else if (connectionResult.hasResolution()) {
            try {
                mResolvingError = true;
                connectionResult.startResolutionForResult(getActivity(), REQUEST_RESOLVE_ERROR);
            } catch (IntentSender.SendIntentException e) {
                // There was an error with the resolution intent. Try again.
                if (mGoogleApiClient != null)
                    mGoogleApiClient.connect();
            }
        } else {
            // Show dialog using GoogleApiAvailability.getErrorDialog()
            showErrorDialog(connectionResult.getErrorCode());
            mResolvingError = true;
        }
    }

    private void showErrorDialog(int errorCode) {
        // Create a fragment for the error dialog
        ErrorDialogFragment dialogFragment = new ErrorDialogFragment();
        // Pass the error that should be displayed
        Bundle args = new Bundle();
        args.putInt(ARGS_DIALOG_ERROR, errorCode);
        dialogFragment.setArguments(args);
        dialogFragment.show(getActivity().getSupportFragmentManager(), TAG_DIALOG_ERROR);
    }

    public static class ErrorDialogFragment extends DialogFragment {
        public ErrorDialogFragment() {
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            // Get the error code and retrieve the appropriate dialog
            int errorCode = this.getArguments().getInt(ARGS_DIALOG_ERROR);
            return GoogleApiAvailability.getInstance().getErrorDialog(
                    this.getActivity(),
                    errorCode,
                    REQUEST_RESOLVE_ERROR);
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            mResolvingError = false; // DOES NOT COMPILE
        }
    }
}

请问我在这里应该做什么?

如果我使 ErrorDialogFragment 成为非静态的,我会得到编译错误:

This fragment inner class should be static (GoogleFragment.ErrorDialogFragment)

如果我保持静态 - 我也无法访问变量。

我正在考虑 2 种解决方法来解决我的问题:

  1. 使用 LocalBroadcastManager 将自定义 IntentErrorDialogFragment 发送到 GoogleFragment
  2. GoogleFragment中定义一个自定义方法并通过getSupportFragmentManager().findFragmentByTag()
  3. 访问它

但是否有更简单的解决方案?

更新:

我已将 mResolvingError 字段更改为 public 并尝试了此代码:

    @Override
    public void onDismiss(DialogInterface dialog) {
        GoogleFragment f = (GoogleFragment) getActivity().getSupportFragmentManager().findFragmentByTag(GoogleFragment.TAG);
        if (f != null && f.isVisible()) {
            f.mResolvingError = false;
        }
    }

但我不确定如何正确测试它以及是否需要 f.isVisible()...

更新 2:

也许我应该以某种方式在我的代码中使用 DialogInterface.OnDismissListener with GoogleApiAvailability.getInstance().getErrorDialog

BladeCoder 的评论非常有见地,谢谢。

但是我已经意识到,保存和恢复 mResolvingError 的所有麻烦都是不必要的,因为 startResolutionForResult() 无论如何都会启动一个单独的 Activity 并阻碍我的应用程序 - 所以它不会'我是否旋转设备真的很重要。

这是我启动 GCM 并获取 Google+ 用户数据的最终代码 -

MainActivity.java:

public static final int REQUEST_GOOGLE_PLAY_SERVICES = 1972;
public static final int REQUEST_GOOGLE_PLUS_LOGIN = 2015;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState == null)
        startRegistrationService();
}

private void startRegistrationService() {
    GoogleApiAvailability api = GoogleApiAvailability.getInstance();
    int code = api.isGooglePlayServicesAvailable(this);
    if (code == ConnectionResult.SUCCESS) {
        onActivityResult(REQUEST_GOOGLE_PLAY_SERVICES, Activity.RESULT_OK, null);
    } else if (api.isUserResolvableError(code) &&
        api.showErrorDialogFragment(this, code, REQUEST_GOOGLE_PLAY_SERVICES)) {
        // wait for onActivityResult call (see below)
    } else {
        String str = GoogleApiAvailability.getInstance().getErrorString(code);
        Toast.makeText(this, str, Toast.LENGTH_LONG).show();
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(requestCode) {
        case REQUEST_GOOGLE_PLAY_SERVICES:
            if (resultCode == Activity.RESULT_OK) {
                Intent i = new Intent(this, RegistrationService.class); 
                startService(i); // OK, init GCM
            }
            break;

        case REQUEST_GOOGLE_PLUS_LOGIN:
            if (resultCode == Activity.RESULT_OK) {
                GoogleFragment f = (GoogleFragment) getSupportFragmentManager().
                    findFragmentByTag(GoogleFragment.TAG);
                if (f != null && f.isVisible())
                    f.onActivityResult(requestCode, resultCode, data);
            }
            break;

        default:
            super.onActivityResult(requestCode, resultCode, data);
    }
}

GoogleFragment.java:

public class GoogleFragment extends Fragment
        implements View.OnClickListener,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    public final static String TAG = "GoogleFragment";

    private GoogleApiClient mGoogleApiClient;

    private ImageButton mLoginButton;
    private ImageButton mLogoutButton;

    public GoogleFragment() {
        // required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_google, container, false);

        mGoogleApiClient = new GoogleApiClient.Builder(getContext())
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(Plus.API)
                .addScope(Plus.SCOPE_PLUS_PROFILE)
                .build();

        mLoginButton = (ImageButton) v.findViewById(R.id.login_button);
        mLoginButton.setOnClickListener(this);

        mLogoutButton = (ImageButton) v.findViewById(R.id.logout_button);
        mLogoutButton.setOnClickListener(this);

        return v;
    }

    private void googleLogin() {
        mGoogleApiClient.connect();
    }

    private void googleLogout() {
        if (mGoogleApiClient.isConnecting() || mGoogleApiClient.isConnected())
            mGoogleApiClient.disconnect();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK)
            mGoogleApiClient.connect();
    }

    @Override
    public void onClick(View v) {
        if (v == mLoginButton)
            googleLogin();
        else
            googleLogout();
    }

    @Override
    public void onConnected(Bundle bundle) {
        Person me = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
        if (me != null) {
            String id = me.getId();
            Person.Name name = me.getName();
            String given = name.getGivenName();
            String family = name.getFamilyName();
            boolean female = (me.hasGender() && me.getGender() == 1);

            String photo = null;
            if (me.hasImage() && me.getImage().hasUrl()) {
                photo = me.getImage().getUrl();
                photo = photo.replaceFirst("\bsz=\d+\b", "sz=300");
            }

            String city = "Unknown city";
            List<Person.PlacesLived> places = me.getPlacesLived();
            if (places != null) {
                for (Person.PlacesLived place : places) {
                    city = place.getValue();
                    if (place.isPrimary())
                        break;
                }
            }

            Toast.makeText(getContext(), "Given: " + given + ", Family: " + family + ", Female: " + female + ", City: " + city, Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        // ignore? don't know what to do here...
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        if (connectionResult.hasResolution()) {
            try {
                connectionResult.startResolutionForResult(getActivity(), MainActivity.REQUEST_GOOGLE_PLUS_LOGIN);
            } catch (IntentSender.SendIntentException e) {
                mGoogleApiClient.connect();
            }
        } else {
            int code = connectionResult.getErrorCode();
            String str = GoogleApiAvailability.getInstance().getErrorString(code);
            Toast.MakeText(getContext(), str, Toast.LENGTH_LONG).show();
        }
    }
}