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

クラスは独自のファイルにあるため、この例にはこれらのアノテーションがありません。これは、フラグメントを使用するアクティビティから独立していることを意味します。

あなたの場合、フラグメントはアクティビティ内にあり、静的修飾子を使用しません。これは、Activityインスタンスに関連付けられていることを意味します。

フラグメントをアクティビティインスタンスに依存させることは悪い考えです。これらのクラスは両方とも複雑なライフサイクルを持ち(特にアクティビティが頻繁に破棄および再作成されるため)、互いに独立している必要があります。

EnableGpsDialogFragmentの修飾子を作成する必要がありますstatic

public static class EnableGpsDialogFragment extends DialogFragment {

クラスはそれstaticを囲むクラスのインスタンスに依存しないため、警告は消えます。

詳細については、ネストされたクラスに関するJavaチュートリアルを参照してください。

編集に応じて編集する:クラスが互いのインスタンスに依存しないようになったので、インスタンスを取得する必要があります。これにより、キャストによる一方向のYourActivity呼び出しが可能になり、次のユーザーのみが使用する場合にのみ機能します。enabledLocationSettings()EnableGpsDialogFragmentYourActivity

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

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

このフラグメントが複数のアクティビティで使用される場合は、代わりに各アクティビティで実装されるを作成するinterface必要があります。

于 2013-03-14T16:33:16.080 に答える
4

すべての DialogFragments はパブリックである必要があり、内部クラスの場合は静的である必要があります。また、引数のない public コンストラクターが必要であり、パラメーターの受け渡しには setArguments() のみに依存する必要があります。

これに準拠しないと、しばらくの間、Lint 警告が生成されました。本当にしたい場合は抑制できますが、Android サポート ライブラリ v25 以降では、そうでない DialogFragment を表示しようとすると実際に例外が発生します。次の規則に準拠しないでください。

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

その理由は、前述のように、アプリがバックグラウンドに置かれたときにメモリ不足の状況などでフラグメントを強制的に破棄する場合に備えて、OS がすべてのフラグメントを再作成できる必要があるためです。アプリが再びフォアグラウンドに置かれると、シリアル化されたアプリケーションの状態からフラグメントを再作成できる必要があります。これは、囲んでいる外部クラスのインスタンス以外の非静的内部クラスでは不可能です。 -作成はそのコンテキストから行われません。

残念ながら、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 に答える