402

私が見たAndroidコードのさまざまな部分で:

 public class MyActivity extends Activity {
    public void method() {
       mContext = this;    // since Activity extends Context
       mContext = getApplicationContext();
       mContext = getBaseContext();
    }
 }

しかし、どちらが好ましいのか、どのような状況でどのような状況で使用すべきかについての適切な説明は見つかりません。

これに関するドキュメントへのポインタ、および間違ったものが選択された場合に何が壊れるかについてのガイダンスをいただければ幸いです。

4

8 に答える 8

312

Android のコンテキストに関してはドキュメントがまばらであることには同意しますが、さまざまな情報源からいくつかの事実をまとめることができます。

公式の Google Android 開発者ブログのこのブログ投稿は、主にメモリ リークに対処するために書かれていますが、コンテキストに関するいくつかの有益な情報も提供しています。

通常の Android アプリケーションでは、通常、アクティビティとアプリケーションの 2 種類のコンテキストがあります。

記事をもう少し読むと、2 つの違いとActivity.getApplicationContext()、アクティビティ コンテキストを使用するのではなく、アプリケーション コンテキスト ( )を使用することを検討したい場合について説明されていますthis)。基本的に、アプリケーション コンテキストはアプリケーションに関連付けられており、アプリのライフ サイクル全体を通じて常に同じになります。アクティビティ コンテキストはアクティビティに関連付けられており、画面の向きの変更中にアクティビティが破棄されるため、何度も破棄される可能性があります。そのような。

Android SDK に取り組んでいる Google エンジニアの 1 人である Dianne Hackborn からの投稿以外に、getBaseContext() をいつ使用するかについては、実際には何も見つかりませんでした。

getBaseContext() を使用しないでください。持っている Context を使用してください。

これはandroid-developers ニュースグループの投稿からのものでした。Android に取り組んでいる少数の人々が実際にそのニュースグループを監視して質問に答えているため、そこでも質問することを検討することをお勧めします。

したがって、全体として、可能な場合はグローバル アプリケーション コンテキストを使用することが望ましいと思われます。

于 2009-06-22T14:11:24.700 に答える
55

の使用に関して私が見つけたものは次のcontextとおりです。

1) . 内で、レイアウトとメニューの拡張、コンテキスト メニューの登録、ウィジェットのインスタンス化、他のアクティビティの開始、内での新規作成、環境設定のインスタンス化、または で使用可能なその他のメソッドに使用しActivityます。thisIntentActivityActivity

レイアウトを膨らませる:

View mView = this.getLayoutInflater().inflate(R.layout.myLayout, myViewGroup);

膨張メニュー:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    this.getMenuInflater().inflate(R.menu.mymenu, menu);
    return true;
}

コンテキスト メニューの登録:

this.registerForContextMenu(myView);

ウィジェットのインスタンス化:

TextView myTextView = (TextView) this.findViewById(R.id.myTextView);

開始Activity:

Intent mIntent = new Intent(this, MyActivity.class);
this.startActivity(mIntent);

設定をインスタンス化します。

SharedPreferences mSharedPreferences = this.getPreferenceManager().getSharedPreferences();

2) . アプリケーション全体のクラスの場合getApplicationContext()、このコンテキストはアプリケーションの存続期間にわたって存在するため、使用します。

現在の Android パッケージの名前を取得します。

public class MyApplication extends Application {    
    public static String getPackageName() {
        String packageName = null;
        try {
            PackageInfo mPackageInfo = getApplicationContext().getPackageManager().getPackageInfo(getApplicationContext().getPackageName(), 0);
            packageName = mPackageInfo.packageName;
        } catch (NameNotFoundException e) {
            // Log error here.
        }
        return packageName;
    }
}

アプリケーション全体のクラスをバインドします。

Intent mIntent = new Intent(this, MyPersistent.class);
MyServiceConnection mServiceConnection = new MyServiceConnection();
if (mServiceConnection != null) {
    getApplicationContext().bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
}

3) . Listener およびその他のタイプの Android クラス (ContentObserver など) には、次のようなコンテキスト置換を使用します。

mContext = this;    // Example 1
mContext = context; // Example 2

thisorはcontextクラスのコンテキスト (Activity など) です。

Activityコンテキスト置換:

public class MyActivity extends Activity {
    private Context mContext;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);        
        mContext = this;
    }
}

リスナー コンテキストの置換:

public class MyLocationListener implements LocationListener {
    private Context mContext;
    public MyLocationListener(Context context) {
        mContext = context;
    }
}

ContentObserverコンテキスト置換:

public class MyContentObserver extends ContentObserver {
    private Context mContext;
    public MyContentObserver(Handler handler, Context context) {
        super(handler);
        mContext = context;
    }
}

4) . (インライン/組み込みレシーバーを含む) にはBroadcastReceiver、レシーバー自身のコンテキストを使用します。

外部BroadcastReceiver:

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        if (action.equals(Intent.ACTION_SCREEN_OFF)) {
            sendReceiverAction(context, true);
        }
        private static void sendReceiverAction(Context context, boolean state) {
            Intent mIntent = new Intent(context.getClass().getName() + "." + context.getString(R.string.receiver_action));
            mIntent.putExtra("extra", state);
            context.sendBroadcast(mIntent, null);
        }
    }
}

インライン/埋め込みBroadcastReceiver:

public class MyActivity extends Activity {
    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final boolean connected = intent.getBooleanExtra(context.getString(R.string.connected), false);
            if (connected) {
                // Do something.
            }
        }
    };
}

5) . サービスの場合は、サービス独自のコンテキストを使用します。

public class MyService extends Service {
    private BroadcastReceiver mBroadcastReceiver;
    @Override
    public void onCreate() {
        super.onCreate();
        registerReceiver();
    }
    private void registerReceiver() {
        IntentFilter mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        this.mBroadcastReceiver = new MyBroadcastReceiver();
        this.registerReceiver(this.mBroadcastReceiver, mIntentFilter);
    } 
}

6) . Toasts の場合、通常は を使用getApplicationContext()しますが、可能であれば、Activity、Service などから渡されたコンテキストを使用します。

アプリケーションの使用コンテキスト:

Toast mToast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG);
mToast.show();

ソースから渡されたコンテキストを使用:

public static void showLongToast(Context context, String message) {
    if (context != null && message != null) {
        Toast mToast = Toast.makeText(context, message, Toast.LENGTH_LONG);
        mToast.show();
    }
}

getBaseContext()最後に、 Android のフレームワーク開発者のアドバイスに従って使用しないでください。

更新:使用例を追加しContextます。

于 2012-12-19T04:43:40.140 に答える
13

数日前にこのスレッドを読み、同じ質問を自問しました。これを読んだ後の私の決定は単純でした:常にapplicationContextを使用してください。

しかし、これで問題が発生しました。それを見つけるのに数時間を費やし、それを解決するのに数秒かかりました... (一言を変える...)

Spinner を含むビューをインフレートするために LayoutInflater を使用しています。

したがって、次の 2 つの可能性があります。

1)

    LayoutInflater layoutInflater = LayoutInflater.from(this.getApplicationContext());

2)

    LayoutInflater layoutInflater = LayoutInflater.from(this.getBaseContext());

次に、私はこのようなことをしています:

    // managing views part
    View view = ContactViewer.mLayoutInflater.inflate(R.layout.aViewContainingASpinner, theParentView, false);
    Spinner spinner = (Spinner) view.findViewById(R.id.theSpinnerId);
    String[] myStringArray = new String[] {"sweet","love"};

    // managing adapter part
    // The context used here don't have any importance -- both work.
    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this.getApplicationContext(), myStringArray, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);

    theParentView.addView(view);

私が気付いたこと: アプリケーション コンテキストで linearLayout をインスタンス化した場合、アクティビティでスピナーをクリックすると、キャッチされない例外が発生します。私の間違いがどこにあったかを見つける時間の...)。

baseContext を使用すると、コンテキスト メニューが開き、選択肢の中から選択できるようになります。

だからここに私の結論があります:アクティビティでcontextMenuを扱うときにbaseContextが必要であるよりも(私はそれ以上テストしていません)...

テストは API 8 でコーディングされており、HTC Desire、android 2.3.3 でテストされています。

これまでのところ、私のコメントがあなたを退屈させていないことを願っています。幸せなコーディング;-)

于 2012-01-06T17:14:49.270 に答える
6

まず、可能な限り appcontext を使用することに同意します。それから活動中の「これ」。ベースコンテキストが必要になったことは一度もありません。

私のテストでは、ほとんどの場合、それらを交換できます。ほとんどの場合、コンテキストを取得する理由は、ファイル、設定、データベースなどにアクセスするためです。これらのデータは、最終的にアプリのプライベート データ フォルダー (/data/data/) にファイルとして反映されます。使用するコンテキストに関係なく、それらは同じフォルダー/ファイルにマップされるため、問題ありません。

それが私が観察したことです。区別したほうがいい場合もあるかもしれません。

于 2010-03-20T08:48:21.677 に答える
3

場合によっては、スレッドで何かを実行するときに、アプリケーション コンテキストよりもアクティビティ コンテキストを使用することがあります。スレッドの実行が完了し、呼び出し元のアクティビティに結果を返す必要がある場合は、ハンドラーを含むそのコンテキストが必要です。

((YourActivity) context).yourCallbackMethod(yourResultFromThread, ...);
于 2010-09-24T23:29:29.740 に答える
0

私はこれを使用しただけで、 (JavaとAndroidの両方への非常に緑のnoob)getBaseContextから乾杯するときにのみ使用しました。onClickこれは、クリッカーがアクティビティに直接含まれていてgetBaseContext、匿名の内部クリッカーで使用する必要がある場合に使用します。getBaseContextおそらく、内部クラスが隠れているアクティビティのコンテキストを返すことです 。

于 2011-12-12T17:02:36.227 に答える