문제

내가 본 다양한 안드로이드 코드에서 :

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

그러나 나는 그다지 좋은 설명을 찾을 수 없으며 어떤 상황에서 사용해야하는 상황에서는 찾을 수 없습니다.

이것에 대한 문서화에 대한 지침과 잘못된 것을 선택하면 무엇이 끊어 질지에 대한 지침은 대단히 감사 할 것입니다.

도움이 되었습니까?

해결책

나는 Android의 상황과 관련하여 문서가 드물다는 데 동의하지만 다양한 출처에서 몇 가지 사실을 함께 할 수 있습니다.

이 블로그 게시물 공식 Google Android Developers 블로그에서 주로 메모리 누출을 해결하기 위해 작성되었지만 상황에 대한 좋은 정보도 제공합니다.

정기적 인 Android 응용 프로그램에는 일반적으로 두 가지 종류의 상황, 활동 및 응용 프로그램이 있습니다.

기사를 조금 더 읽으면 둘의 차이점과 응용 프로그램 컨텍스트 사용을 고려할 때 (Activity.getApplicationContext()) 활동 컨텍스트를 사용하기보다는 this). 기본적으로 응용 프로그램 컨텍스트는 응용 프로그램과 관련이 있으며 앱의 수명주기 전체에서 항상 동일합니다. 활동 컨텍스트가 활동과 관련되어 있으며 화면 방향이 변경되고 활동이 파괴 될 때 여러 번 파괴 될 수 있습니다. 그런.

Android SDK에서 작업하는 Google 엔지니어 중 한 명인 Dianne Hackborn의 게시물 이외의 GetBaseContext ()를 사용하는시기에 대해서는 아무것도 찾을 수 없었습니다.

getBaseContext ()를 사용하지 말고 컨텍스트를 사용하십시오.

그것은 그 게시물에서 나온 것입니다 안드로이드 개발자 뉴스 그룹, Android 실제 모니터에서 일하는 소수의 사람들이 뉴스 그룹과 질문에 답변하기 때문에 질문을하는 것을 고려할 수 있습니다.

따라서 전반적으로 가능하면 글로벌 응용 프로그램 컨텍스트를 사용하는 것이 바람직합니다.

다른 팁

다음은 사용과 관련하여 내가 찾은 것입니다 context:

1) . 안에 Activity 그 자체, 사용 this 레이아웃 및 메뉴를 팽창시키기 위해 컨텍스트 메뉴를 등록하고 위젯을 인스턴스화하고 기타 활동을 시작하고 새 생성 Intent 안에 Activity, 인스턴스화 선호도 또는 Activity.

레이아웃 팽창 :

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) . 청취자 및 기타 유형의 Android 클래스 (예 : ContentObserver)의 경우 다음과 같은 컨텍스트 대체를 사용하십시오.

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

어디 this 또는 context 클래스 (활동 등)의 맥락입니다.

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) . 토스트의 경우 일반적으로 사용하십시오 getApplicationContext(), 그러나 가능하면 활동, 서비스 등에서 전달 된 컨텍스트를 사용하십시오.

응용 프로그램의 컨텍스트 사용 :

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 용법.

나는 며칠 전에이 스레드를 읽고 나 자신에게 같은 질문을했다. 이것을 읽은 후의 결정은 간단했습니다. 항상 ApplicationContext를 사용하십시오.

그러나 나는 이것에 문제가 있었고, 그것을 찾기 위해 몇 시간을 보냈고, 그것을 해결하기 위해 몇 초를 보냈습니다 ... (한 단어 변경 ...)

스피너가 포함 된 뷰를 팽창시키기 위해 LayoutInflater를 사용하고 있습니다.

그래서 여기에 두 가지 가능성이 있습니다.

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);

내가 알아 차린 것 : ApplicationContext로 선형 레이 아웃을 인스턴스화 한 경우 활동의 스피너를 클릭하면 Dalvik 가상 머신에서 오는 예외가 발생하지 않습니다 (코드가 아닌, 내가 많이 소비 한 이유입니다. 내 실수는 어디에 있었는지 찾을 시간입니다 ...).

BaseContext를 사용하면 괜찮습니다. 상황에 맞는 메뉴가 열리고 선택한 선택 중에서 선택할 수 있습니다.

그래서 여기에 내 결론이 있습니다 : 나는 당신의 활동에서 ContextMenu를 다룰 때 Basecontext가 필요하다고 생각합니다 ...

이 테스트는 API 8으로 코딩되어 HTC 욕망 인 Android 2.3.3에서 테스트되었습니다.

내 의견이 지금까지 당신을 지루하지 않았기를 바랍니다. 행복한 코딩 ;-)

먼저, 가능할 때마다 AppContext를 사용해야한다는 데 동의합니다. 그런 다음 활동에서 "이것". 나는 BaseContext가 필요하지 않았습니다.

내 테스트에서 대부분의 경우 교환 될 수 있습니다. 대부분의 경우 컨텍스트를 보유하려는 이유는 파일, 환경 설정, 데이터베이스 등에 액세스하는 것입니다. 이러한 데이터는 결국 앱의 개인 데이터 폴더 (/data/data/)의 파일로 반영됩니다. 어떤 컨텍스트를 사용하든 동일한 폴더/파일에 매핑되므로 괜찮습니다.

그것이 내가 관찰 한 것입니다. 어쩌면 당신이 그들을 구별 해야하는 경우가있을 수 있습니다.

경우에 따라 스레드에서 무언가를 실행할 때 응용 프로그램 컨텍스트를 통해 활동 컨텍스트를 사용할 수 있습니다. 스레드가 실행을 완료하고 결과를 발신자 활동으로 되돌려야하는 경우 핸들러와 함께 해당 컨텍스트가 필요합니다.

((YourActivity) context).yourCallbackMethod(yourResultFromThread, ...);

간단한 말로

getApplicationContext() 메소드 이름이 제안한대로 앱의 어느 곳에서나 액세스 할 수있는 응용 프로그램의 광범위한 세부 사항을 알 수 있습니다. 따라서 서비스 구속력, 방송 등록 등을 사용할 수 있습니다. Application context 앱이 종료 될 때까지 살아남을 것입니다.

getActivity() 또는 this 앱이 제공 한 앱 레벨 세부 사항도 볼 수있는 현재 화면을 알 수 있도록합니다. application context. 그래서 현재 화면에 대해 알고 싶은 것은 무엇이든 Window ActionBar Fragementmanger 그리고이 맥락에서도 가능합니다. 기본적으로 Activity 연장하다 Context. 이러한 맥락은 현재 구성 요소 (활동)가 살아있을 때까지 살아날 것입니다.

나는 이것 만 사용했다 getBaseContext An에서 토스트 할 때 onClick (Java와 Android 모두에게 매우 녹색 멍청이). 내 클릭 커가 활동에 직접있을 때 이것을 사용하고 사용해야합니다. getBaseContext 익명의 내부 클릭 커에서. 나는 그것이 거의 속임수라고 생각합니다 getBaseContext, 아마도 내면의 클래스가 숨어있는 활동의 맥락을 반환하고있을 것입니다.

혼란은 (표면에) 식별 할 수있는 차이가없는 컨텍스트에 액세스하는 방법이 많이 있다는 사실에서 비롯됩니다. 다음은 활동에서 컨텍스트에 액세스 할 수있는 가장 일반적인 방법 중 4 가지입니다.

getContext()
getBaseContext()
getApplicationContext()
getActionBar().getThemedContext() //new

맥락이란 무엇입니까?나는 개인적으로 문맥을 주어진 시간에 당신의 신청서의 상태로 생각하고 싶습니다. 응용 프로그램 컨텍스트는 애플리케이션의 글로벌 또는 기본 구성을 나타내며 활동 또는 서비스가이를 구축 할 수 있으며 응용 프로그램의 구성 인스턴스 또는이를위한 전이 상태를 나타냅니다.

Android.content.context의 소스를 보면 컨텍스트가 추상 클래스이고 클래스에 대한 의견은 다음과 같습니다.

응용 프로그램 환경에 대한 글로벌 정보에 대한 인터페이스. 이것은 Android 시스템에서 구현을 제공하는 추상 클래스입니다. 액세스 할 수 있습니다 application-specific 자원과 클래스, 그리고 상향 호출 application-level 출시 활동, 방송 및 수신 의도 등과 같은 운영.이 점에서 벗어나는 것은 컨텍스트가 애플리케이션 수준 및 시스템 수준 리소스에 액세스하는 공통 구현을 제공한다는 것입니다. 응용 프로그램 수준 리소스는 문자열 리소스와 같은 것에 액세스 할 수 있습니다. [getResources()] 또는 자산 [getAssets()] 그리고 시스템 수준 리소스는 귀하가 액세스 할 수있는 것입니다 Context.getSystemService().

사실, 방법에 대한 의견을 살펴 보고이 개념을 강화하는 것 같습니다.

getSystemService(): 핸들을 a로 되돌립니다 system-level 이름으로 서비스. 반환 된 객체의 클래스는 요청 된 이름에 따라 다릅니다.getResources(): 응용 프로그램 패키지의 리소스 인스턴스를 반환합니다.getAssets(): 응용 프로그램 패키지의 리소스 인스턴스를 반환합니다. 문맥에서 추상 클래스에서 위의 모든 방법이 추상적이라는 점을 지적 할 가치가 있습니다! GetSystemService (클래스)의 하나의 인스턴스 만 구현되어 있으며 이는 추상 방법을 호출합니다. 즉, 이들에 대한 구현은 주로 구현 클래스가 제공해야합니다. 여기에는 다음이 포함됩니다.

ContextWrapper
Application
Activity
Service
IntentService

API 문서를 살펴보면 클래스의 계층 구조는 다음과 같습니다.

문맥

| - ContextWrapper

| - - 응용 프로그램

| - - ContextTheMewrapper

| - - - - 활동

| - - 서비스

| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

우리는 그것을 알고 있기 때문에 Context 그 자체가 통찰력을 제공하지 않고, 우리는 나무를 내려 가서 ContextWrapper 그리고 거기에도 많지 않다는 것을 인식하십시오. 응용 프로그램이 확장되므로 ContextWrapper, 그것이 제공 한 구현을 무시하지 않기 때문에 볼만 할 것이 많지 않습니다. ContextWrapper. 이것은 컨텍스트에 대한 구현이 OS에 의해 제공되고 API. ContextImpl 클래스의 소스를 살펴보면 컨텍스트를위한 구체적인 구현을 볼 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top