Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/217.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 内部DialogFragment类是否应该是静态的?_Android_Android Dialogfragment - Fatal编程技术网

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

Android 内部DialogFragment类是否应该是静态的?,android,android-dialogfragment,Android,Android Dialogfragment,这是我用来学习Android的项目中的一段代码: private void enableLocationSettings() { Intent settingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(settingsIntent); } @SuppressLint("ValidFragment") public class EnableGpsDialogFragme

这是我用来学习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;

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

在您的例子中,您的片段位于活动中,并且不使用静态修饰符。这意味着它绑定到活动实例

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

您需要使
启用gpsdialogfragment
的修饰符
为static

public static class EnableGpsDialogFragment extends DialogFragment {
静态类不依赖于封闭类的实例,因此警告将消失

有关更多信息,请阅读上的Java教程

编辑以响应您的编辑: 既然这些类不依赖于彼此的实例,那么您必须拿出一个
YourActivity
的实例,这样您就可以调用
enabledLocationSettings()
一种方法是通过强制转换,并且只有当
EnableGpsDialogFragment
仅由
YourActivity
使用时才会起作用:

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

如果此片段将被多个活动使用,您应该使用。

不应该

在我看来,我不希望DialogFragment(您的NetworkConnectionError)是静态的,因为我希望能够从中调用包含类(活动)的变量或方法。
所以它不会是静态的。 但我也不想生成MemoryLeak。
那么解决方案是什么呢?
很简单,当你在上面的时候,确保你杀死了你的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");
}
这样可以避免内存泄漏(因为它很糟糕),并确保没有一个静态片段无法访问活动的字段和方法。
在我看来,这是处理这个问题的好方法。

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

一段时间以来,如果不遵守这一点,会产生一个Lint警告,如果您真的想要,您可以抑制该警告,但从Android支持库v25及更高版本开始,如果尝试显示不符合以下规则的DialogFragment,您实际上会得到一个异常:

java.lang.IllegalStateException:Fragment TestActivity$TestDialogFrament必须是公共静态类,才能从实例状态正确地重新创建。

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


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

谢谢,但将静态修饰符添加到EnableGpsDialogFragment会迫使我将静态修饰符添加到私有void enableLocationSettings()。如果我添加它,就会出现一个新的错误:无法从类型中静态引用非静态方法startActivity(Intent)Activity@szpic这是因为您对问题的编辑现在包括对
enableLocationSettings()的调用
为了避免这种情况,可以使用弱引用来引用活动中需要的任何内容。然后在使用之前,检查它是否仍然有效。每次销毁/创建活动时都应设置此选项,以确保其有效。添加关于静态片段:如果不是静态创建的,它们可能会泄漏此上下文中的内存,因为它们可能持有对旧活动的引用,而旧活动在其他情况下不再可访问,并且应该已被垃圾收集。谢谢您挽救了我的一天。我希望我能给你更多的投票!DialogFragments应该是公共静态类,带有一个公共的无操作构造函数,就这么简单。如果没有,系统将无法在内存不足等情况下重新创建片段,从support library v25开始,如果尝试显示不满足上述约束的DialogFragment,您的应用程序将崩溃:
java.lang.IllegalStateException:Fragment TestActivity$TestDialogFramint必须是公共静态类,才能从实例状态正确重新创建。
oops,输入:no op->no argNo。他们不应该。我可以自己重新创建它们。再说一次,在大多数正常情况下,你为什么会喜欢这样?内存不足的情况是一个真正的威胁,因为我们在廉价智能手机中至少有2GB的RAM…:)我一直不明白谷歌为什么要重新创建我的对话片段,如果他们不得不销毁它们的话——我可以自己做,而且已经这么做了(我使用v23,不会升级)。部分原因是,这么多应用程序行为不正常,基本上一直在运行,或者由于频繁的广播意图而不断重新启动。安卓N和O正在严格解决这一问题。如果50个应用程序想要一直运行,那么将有大量的应用程序从内存中交换。另外,请记住,在1080p屏幕上,一个位图是8MB。我不太清楚我是否理解为什么你会想完全手动重新创建状态,但我们都有自己的处理方法。。。
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");
}