9

这是我用来学习 Android 的项目中的一段代码:

private void enableLocationSettings() {
    Intent settingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
    startActivity(settingsIntent);
}

@SuppressLint("ValidFragment")
public class EnableGpsDialogFragment extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
            .setTitle("Tytuł")
            .setMessage("wiadomosc")
            .setPositiveButton("odpal", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    enableLocationSettings();
                }

            })
            .create();
    }
} 

如您所见,我必须添加@SuppressLint才能使我的应用程序正常工作,但在指南中,此注释不是必需的。

我究竟做错了什么?

这是我的进口:

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.DialogFragment;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
import android.widget.ToggleButton;
4

3 回答 3

20

该示例没有这些注释,因为该类位于其自己的文件中。这意味着它独立于使用 Fragment 的 Activity。

在您的情况下,您的 Fragment 位于 Activity 内,并且不使用 static 修饰符。这意味着它与 Activity 实例相关联。

让 Fragment 依赖于 Activity 实例是一个坏主意,这两个类都有复杂的生命周期(特别是因为 Activity 经常被销毁和重新创建)并且应该彼此独立。

您将需要 makeEnableGpsDialogFragment的修饰符static

public static class EnableGpsDialogFragment extends DialogFragment {

一个static类不依赖于封闭类的实例,因此警告将消失。

有关更多信息,请阅读有关嵌套类的 Java 教程。

编辑以响应您的编辑:现在这些类不依赖于彼此的实例,您将不得不取出一个实例,YourActivity因此您可以通过强制转换调用enabledLocationSettings()一种方法,并且仅在EnableGpsDialogFragment仅由以下人员使用时才有效YourActivity

@Override
public void onClick(DialogInterface dialog, int which) {
  enableLocationSettings();
}

@Override
public void onClick(DialogInterface dialog, int which) {
  ((YourActivity)getActivity()).enableLocationSettings();
}

如果这个 Fragment 将被多个 Activity 使用,您应该创建一个interface由每个 Activity 来实现

于 2013-03-14T16:33:16.080 回答
4

所有 DialogFragments 都应该是公共的,并且 - 如果是内部类 - 是静态的。它们还应该有一个公共的无参数构造函数,并且只依赖 setArguments() 进行参数传递。

一段时间以来,未能遵守这一规定会产生一个 Lint 警告,如果你真的想要,你可以抑制它,但从 Android 支持库 v25 及更高版本开始,如果试图显示一个不存在的 DialogFragment,你实际上会得到一个异常遵守这些规则:

java.lang.IllegalStateException: Fragment TestActivity$TestDialogFrament must be a public static class to be properly recreated from instance state.

如前所述,原因是操作系统必须能够重新创建所有片段,以防在将应用程序置于后台时,诸如内存不足的情况迫使它销毁片段。当应用程序再次置于前台时,应该可以从序列化的应用程序状态重新创建片段,这对于非静态内部类来说是不可能的,而不是来自封闭外部类的实例,并且重新-creation 不是从那个上下文中完成的。

不幸的是,这使对话框变得更加复杂,因为创建一个覆盖 onCreateDialog 的匿名子类通常非常方便。但是,这样的对话框根本无法重新创建。

于 2016-10-26T10:18:59.430 回答
1

不应该!

从我的角度来看,我不希望我的 DialogFragment(您的 NetworkConnectionError)是静态的,因为我希望能够从中调用我的包含类(Activity)的变量或方法。
所以它不会是静态的。但我也不想产生 memoryLeaks。
那么解决方案是什么?
很简单,当你进入 onStop 时,确保你杀死你的 DialogFragment,就这么简单。所以代码看起来像这样:

public class CarActivity extends AppCompatActivity{

/**
 * The DialogFragment networkConnectionErrorDialog 
 */
private NetworkConnectionError  networkConnectionErrorDialog ;
//...  your code ...//
@Override
protected void onStop() {
    super.onStop();
    //invalidate the DialogFragment to avoid stupid memory leak
    if (networkConnectionErrorDialog != null) {
        if (networkConnectionErrorDialog .isVisible()) {
            networkConnectionErrorDialog .dismiss();
        }
        networkConnectionErrorDialog = null;
    }
}
/**
 * The method called to display your dialogFragment
 */
private void onDeleteCurrentCity(){
    FragmentManager fm = getSupportFragmentManager();
     networkConnectionErrorDialog =(DeleteAlert)fm.findFragmentByTag("networkError");
    if(networkConnectionErrorDialog ==null){
        networkConnectionErrorDialog =new DeleteAlert();
    }
    networkConnectionErrorDialog .show(getSupportFragmentManager(), "networkError");
}

这样你就可以避免内存泄漏(因为它很糟糕)并且你确保你没有一个他妈的静态片段无法访问你的活动的字段和方法。从我的角度来看,这是处理该问题的好方法。

于 2016-03-10T12:33:26.150 回答