内部DialogFragment类是否应该是静态的?

时间:2013-03-14 16:30:06

标签: android android-dialogfragment

这是我用来学习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以使我的应用有效,但在guide上无需注释。

我做错了什么?

以下是我的导入:

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;

3 个答案:

答案 0 :(得分:20)

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

在您的情况下,您的Fragment位于Activity内部,不使用static修饰符。这意味着它与Activity实例绑定。

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

您需要制作EnableGpsDialogFragment的修饰符static

public static class EnableGpsDialogFragment extends DialogFragment {

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

有关详细信息,请阅读nested classes上的Java教程。

编辑以响应您的修改: 既然这些类不依赖于彼此的实例,那么你必须得到一个YourActivity的实例,这样你就可以通过强制转换来调用enabledLocationSettings(),只有{{1}才能使用EnableGpsDialogFragment }仅由YourActivity使用:

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

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

如果多个活动将使用此片段,您应该create an interface to be implemented by each Activity instead

答案 1 :(得分:3)

所有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.

原因是,如上所述,操作系统必须能够重新创建所有碎片,以防低内存情况迫使它在应用程序放入后台时破坏碎片。当应用程序再次置于前台时,应该可以从序列化应用程序状态重新创建片段,这对于非静态内部类是不可能的,而不是来自封闭外部类的实例,并且 - 创造不是从那种背景下完成的。

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

答案 2 :(得分:1)

不应该!

从我的角度来看,我不希望我的DialogFragment(你的NetworkConnectionError)是静态的,因为我希望能够从中调用我的包含类(Activity)的变量或方法。
所以它不会是静止的。 但我也不想产生记忆泄漏 那么解决方案是什么?
很简单,当你进入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");
}

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