从自定义 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 种解决方法来解决我的问题:
- 使用
LocalBroadcastManager
将自定义 Intent
从 ErrorDialogFragment
发送到 GoogleFragment
- 在
GoogleFragment
中定义一个自定义方法并通过getSupportFragmentManager().findFragmentByTag()
访问它
但是否有更简单的解决方案?
更新:
我已将 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();
}
}
}
成功遵循指南后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 种解决方法来解决我的问题:
- 使用
LocalBroadcastManager
将自定义Intent
从ErrorDialogFragment
发送到GoogleFragment
- 在
GoogleFragment
中定义一个自定义方法并通过getSupportFragmentManager().findFragmentByTag()
访问它
但是否有更简单的解决方案?
更新:
我已将 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();
}
}
}