안드로이드에서 '컨텍스트'를 얻는 정적 방법?
-
18-09-2019 - |
문제
전류를 얻는 방법이 있습니까? Context
정적 메소드 내부 인스턴스?
변경할 때마다 '컨텍스트'인스턴스를 저장하는 것을 싫어하기 때문에 그런 식으로 찾고 있습니다.
해결책
이 작업을 수행:
Android Manifest 파일에서 다음을 선언하십시오.
<application android:name="com.xyz.MyApplication">
</application>
그런 다음 수업을 작성하십시오.
public class MyApplication extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
MyApplication.context = getApplicationContext();
}
public static Context getAppContext() {
return MyApplication.context;
}
}
이제 어디서나 전화하십시오 MyApplication.getAppContext()
응용 프로그램 컨텍스트를 정적으로 얻으려면
다른 팁
애플리케이션 컨텍스트를 얻기 위해 편리한 방법을 원하는 대부분의 앱은 자신의 클래스를 생성하여 확장됩니다. android.app.Application
.
가이드
다음과 같이 프로젝트에서 수업을 먼저 만들어이를 달성 할 수 있습니다.
import android.app.Application;
import android.content.Context;
public class App extends Application {
private static Application sApplication;
public static Application getApplication() {
return sApplication;
}
public static Context getContext() {
return getApplication().getApplicationContext();
}
@Override
public void onCreate() {
super.onCreate();
sApplication = this;
}
}
그런 다음 AndroidManifest에서 AndroidManifest.xml의 태그에서 클래스 이름을 지정해야합니다.
<application
...
android:name="com.example.App" >
...
</application>
그런 다음 다음을 사용하여 모든 정적 메소드에서 응용 프로그램 컨텍스트를 검색 할 수 있습니다.
public static void someMethod() {
Context context = App.getContext();
}
경고
위의 프로젝트에 같은 것을 추가하기 전에 문서의 내용을 고려해야합니다.
일반적으로 서브 클래스 애플리케이션이 필요하지 않습니다. 대부분의 상황에서 정적 싱글 톤은보다 모듈 식 방식으로 동일한 기능을 제공 할 수 있습니다. 싱글 톤이 글로벌 컨텍스트 (예 : 방송 수신기를 등록하기 위해)가 필요한 경우,이를 검색 할 수있는 함수는 싱글 톤을 처음 구성 할 때 내부적으로 컨텍스트를 사용하는 컨텍스트를 제공 할 수 있습니다.
반사
반사를 사용하여 응용 프로그램 컨텍스트를 얻는 또 다른 방법도 있습니다. 반사는 종종 안드로이드에서 내려다 보며 개인적으로 이것이 제작에 사용해서는 안된다고 생각합니다.
응용 프로그램 컨텍스트를 검색하려면 숨겨진 클래스에서 메소드를 호출해야합니다 (ActivityThread) API 1 이후로 사용할 수있는) :
public static Application getApplicationUsingReflection() throws Exception {
return (Application) Class.forName("android.app.ActivityThread")
.getMethod("currentApplication").invoke(null, (Object[]) null);
}
숨겨진 수업이 하나 더 있습니다 (appglobals)는 응용 프로그램 컨텍스트를 정적으로 얻을 수있는 방법을 제공합니다. 그것은 컨텍스트를 사용합니다 ActivityThread
따라서 다음 방법과 위에 게시 된 방법에는 차이가 없습니다.
public static Application getApplicationUsingReflection() throws Exception {
return (Application) Class.forName("android.app.AppGlobals")
.getMethod("getInitialApplication").invoke(null, (Object[]) null);
}
행복한 코딩!
응용 프로그램 컨텍스트를 얻는 것에 대해 이야기하고 있다고 가정하면 @rohit ghatol 확장 응용 프로그램에서 제안한대로 구현했습니다. 그런 일이 일어 났을 때, 그러한 방식으로 검색된 맥락이 항상 널이 없다는 보장은 없다는 것입니다. 필요할 때, 그것은 일반적으로 시간이 지연 될 수없는 도우미를 초기화하거나 자원을 얻기를 원하기 때문입니다. 널 케이스를 처리하면 도움이되지 않습니다. 그래서 나는 기본적으로 Android 아키텍처와 싸우고 있다는 것을 이해했습니다. 문서
참고 : 일반적으로 서브 클래스 응용 프로그램이 필요하지 않습니다. 대부분의 상황에서 정적 싱글 톤은보다 모듈 식 방식으로 동일한 기능을 제공 할 수 있습니다. 싱글 톤에 글로벌 컨텍스트가 필요한 경우 (예 : 방송 수신기를 등록하기 위해) 컨텍스트를 포함시킬 때 컨텍스트 인수로 context.getApplicationContext ()를 포함하십시오.
그리고 설명했다 Dianne Hackborn
애플리케이션이 도출 할 수있는 유일한 이유는 Pre-1.0 개발 중에 응용 프로그램 개발자 중 한 명이 지속적으로 도출 할 수있는 최상위 응용 프로그램 개체를 가질 필요가있어서 "정상"을 가질 수 있도록 계속해서 나에게 버그를두고 있었기 때문입니다. "그들에게 응용 프로그램 모델과 나는 결국 입었다. 나는 영원히 그것을 후회할 것이다. :)
그녀는 또한이 문제에 대한 해결책을 제안하고 있습니다.
원하는 것이 앱의 다른 부분에서 공유 할 수있는 글로벌 상태라면 싱글 톤을 사용하십시오. [...] 그리고 이것은 이러한 것들을 어떻게 관리 해야하는지 더 자연스럽게 이어집니다.
그래서 내가 한 일은 응용 프로그램을 확장하고 컨텍스트를 싱글 톤 헬퍼의 getinstance ()로 직접 전달하는 동시에 개인 생성자의 응용 프로그램 컨텍스트에 대한 참조를 저장하는 것이 었습니다.
private static MyHelper instance;
private final Context mContext;
private MyHelper(@NonNull Context context) {
mContext = context.getApplicationContext();
}
public static MyHelper getInstance(@NonNull Context context) {
synchronized(MyHelper.class) {
if (instance == null) {
instance = new MyHelper(context);
}
return instance;
}
}
그런 다음 발신자는 로컬 컨텍스트를 도우미에게 전달합니다.
Helper.getInstance(myCtx).doSomething();
따라서이 질문에 올바르게 답변하기 위해 : 신청 컨텍스트에 정적으로 액세스 할 수있는 방법이 있지만, 모두 낙담해야하며, 싱글 톤의 getinstance ()에 로컬 컨텍스트를 전달하는 것을 선호해야합니다.
관심있는 사람은 누구나 더 자세한 버전을 읽을 수 있습니다. FWD 블로그
아니요, 나는 생각하지 않습니다. 불행히도, 당신은 전화를 걸었습니다 getApplicationContext()
~에서 Activity
또는 다른 서브 클래스 중 하나 Context
. 또한, 이것 질문은 다소 관련이 있습니다.
여기에 있습니다 문서화되지 않은 얻는 방법 신청 (컨텍스트) UI 스레드의 어느 곳에서나. 숨겨진 정적 방법에 의존합니다 ActivityThread.currentApplication()
. 적어도 Android 4.x에서 작동해야합니다.
try {
final Class<?> activityThreadClass =
Class.forName("android.app.ActivityThread");
final Method method = activityThreadClass.getMethod("currentApplication");
return (Application) method.invoke(null, (Object[]) null);
} catch (final ClassNotFoundException e) {
// handle exception
} catch (final NoSuchMethodException e) {
// handle exception
} catch (final IllegalArgumentException e) {
// handle exception
} catch (final IllegalAccessException e) {
// handle exception
} catch (final InvocationTargetException e) {
// handle exception
}
이 메소드가 NULL을 반환 할 수 있습니다. 예를 들어 UI 스레드 외부의 메소드를 호출하거나 응용 프로그램이 스레드에 바인딩되지 않습니다.
여전히 사용하는 것이 좋습니다 @Rohitghatol응용 프로그램 코드를 변경할 수있는 경우 솔루션.
컨텍스트를 사용하는 것에 따라 다릅니다. 그 방법에 대한 적어도 하나의 단점을 생각할 수 있습니다.
당신이 만들려고한다면 AlertDialog
~와 함께 AlertDialog.Builder
,, Application
컨텍스트는 작동하지 않습니다. 나는 당신이 현재의 상황이 필요하다고 생각합니다 Activity
...
당신이 사용하기에 열려 있다면 Roboguice, 원하는 클래스에 컨텍스트를 주입 할 수 있습니다. 다음은 Roboguice 2.0을 사용하여 수행하는 방법에 대한 작은 샘플입니다 (이 글을 쓰는 시점에 베타 4).
import android.content.Context;
import android.os.Build;
import roboguice.inject.ContextSingleton;
import javax.inject.Inject;
@ContextSingleton
public class DataManager {
@Inject
public DataManager(Context context) {
Properties properties = new Properties();
properties.load(context.getResources().getAssets().open("data.properties"));
} catch (IOException e) {
}
}
}
나는 이것을 어느 시점에서 사용했습니다.
ActivityThread at = ActivityThread.systemMain();
Context context = at.getSystemContext();
이것은 시스템 서비스를 얻는 데 사용한 유효한 맥락입니다.
그러나 프레임 워크/기본 수정에서만 사용했으며 Android 응용 프로그램에서는 시도하지 않았습니다.
ㅏ 경고 이 맥락에서 방송 수신기에 등록 할 때는 작동하지 않으며 다음과 같이받을 것입니다.
java.lang.securityException : 발신자 패키지가 Process Record에서 실행되지 않습니다.
Kotlin Way:
명백한:
<application android:name="MyApplication">
</application>
myApplication.kt
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
instance = this
}
companion object {
lateinit var instance: MyApplication
private set
}
}
그런 다음 myApplication.instance를 통해 속성에 액세스 할 수 있습니다
매니페스트 파일을 수정하지 않으려면 초기 활동에서 정적 변수에 컨텍스트를 수동으로 저장할 수 있습니다.
public class App {
private static Context context;
public static void setContext(Context cntxt) {
context = cntxt;
}
public static Context getContext() {
return context;
}
}
활동 (또는 활동)이 시작될 때 상황을 설정합니다.
// MainActivity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set Context
App.setContext(getApplicationContext());
// Other stuff
}
메모: 다른 모든 대답과 마찬가지로 이것은 잠재적 인 메모리 누출입니다.
코 틀린
open class MyApp : Application() {
override fun onCreate() {
super.onCreate()
mInstance = this
}
companion object {
lateinit var mInstance: MyApp
fun getContext(): Context? {
return mInstance.applicationContext
}
}
}
그리고 같은 맥락을 얻으십시오
MyApp.mInstance
또는
MyApp.getContext()
나는 당신이 신체가 필요하다고 생각합니다 getAppContext()
방법:
public static Context getAppContext()
return MyApplication.context;
다음을 사용할 수 있습니다.
MainActivity.this.getApplicationContext();
MainActivity.java :
...
public class MainActivity ... {
static MainActivity ma;
...
public void onCreate(Bundle b) {
super...
ma=this;
...
다른 수업 :
public ...
public ANY_METHOD... {
Context c = MainActivity.ma.getApplicationContext();
에 따르면 이 소스 ContextWrapper를 확장하여 자신의 컨텍스트를 얻을 수 있습니다
public class SomeClass extends ContextWrapper {
public SomeClass(Context base) {
super(base);
}
public void someMethod() {
// notice how I can use "this" for Context
// this works because this class has it's own Context just like an Activity or Service
startActivity(this, SomeRealActivity.class);
//would require context too
File cacheDir = getCacheDir();
}
}
단순히 모든 호출을 다른 컨텍스트로 위임하는 컨텍스트 구현을 위임합니다. 원래 컨텍스트를 변경하지 않고 동작을 수정하기 위해 서브 클래싱 할 수 있습니다.
나는 이것에 도움이되는 싱글 톤 디자인 패턴의 변형을 사용합니다.
import android.app.Activity;
import android.content.Context;
public class ApplicationContextSingleton {
private static Activity gContext;
public static void setContext( Activity activity) {
gContext = activity;
}
public static Activity getActivity() {
return gContext;
}
public static Context getContext() {
return gContext;
}
}
그런 다음 전화합니다 ApplicationContextSingleton.setContext( this );
내 Activity.oncreate () 그리고 ApplicationContextSingleton.setContext( null );
안에 ondestroy ();
방금 Android라는 jQuery에서 영감을 얻은 프레임 워크를 발표했습니다 증기 API 그것은 앱 개발을 더 간단하게 만드는 것을 목표로합니다.
중앙 $
외관 수업 a WeakReference
(Ethan Nicholas의 이것에 대한 Awesome Java 블로그 게시물에 대한 링크). Activity
호출을 통해 검색 할 수있는 컨텍스트 :
$.act()
ㅏ WeakReference
쓰레기 수집이 원래 물체를 되 찾는 것을 방지하지 않고 참조를 유지하므로 메모리 누출에 문제가되지 않아야합니다.
물론 단점은 당신이 위험을 감수한다는 것입니다. $.act()
Null을 반환 할 수 있습니다. 나는 아직이 시나리오를 발견하지 못했기 때문에 언급할만한 가치가있는 최소한의 위험 일 것입니다.
사용하지 않는 경우 컨텍스트를 수동으로 설정할 수도 있습니다. VaporActivity
당신으로 Activity
수업:
$.act(Activity);
또한, 많은 것 증기 API 프레임 워크는이 저장된 컨텍스트를 본질적으로 사용하여 프레임 워크를 사용하기로 결정한 경우 직접 저장할 필요가 없음을 의미 할 수 있습니다. 확인하십시오 대지 자세한 정보 및 샘플.
도움이되기를 바랍니다. :)
어떤 이유로 든 신청/활동을 확장하는 것뿐만 아니라 일부 공장 또는 도우미 수업의 경우 어떤 클래스에서 신청 컨텍스트를 원한다면. 다음 싱글 톤을 앱에 추가 할 수 있습니다.
public class GlobalAppContextSingleton {
private static GlobalAppContextSingleton mInstance;
private Context context;
public static GlobalAppContextSingleton getInstance() {
if (mInstance == null) mInstance = getSync();
return mInstance;
}
private static synchronized GlobalAppContextSingleton getSync() {
if (mInstance == null) mInstance =
new GlobalAppContextSingleton();
return mInstance;
}
public void initialize(Context context) {
this.context = context;
}
public Context getApplicationContext() {
return context;
}
}
그런 다음 응용 프로그램 클래스의 OnCreate에서 초기화하십시오.
GlobalAppContextSingleton.getInstance().initialize(this);
전화하여 어디서나 사용하십시오
GlobalAppContextSingleton.getInstance().getApplicationContext()
그러나이 접근법은 응용 프로그램 컨텍스트 외에는 권장하지 않습니다. 메모리 누출을 일으킬 수 있습니다.
Rohit의 대답이 맞습니다. 그러나 Androidstudio의 "Instant Run"은 static Context
내가 아는 한 코드의 속성.
그래서 메모리 누출을 일으키기 때문에 허용 된 답변을 수정했습니다. 이것이 제가 생각해 낸 것입니다 ...
AndroidManifest.xml
<application android:name="com.xyz.MyApplication">
...
</application>
myApplication.java
public class MyBakingAppContext extends Application {
private static Object mContext;
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
}
public static Context getAppContext() {
return (Context)mContext;
}
}
내가 실제로 한 일은 컨텍스트를 객체에 할당하고 객체를 컨텍스트로 반환하는 것입니다 (컨텍스트로 캐스팅). 도움이되기를 바랍니다.
Kotlin에서는 동반자 객체에 컨텍스트/앱 컨텍스트를 넣는 것입니다. Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)
또는 다음과 같은 것을 사용하는 경우 :
companion object {
lateinit var instance: MyApp
}
메모리 누출을 발견하지 못하는 것은 보풀을 속이는 것입니다. 응용 프로그램 클래스와 그 후손이 컨텍스트이기 때문에 앱 인스턴스는 여전히 메모리 누출을 생성 할 수 있습니다.
또는 기능 인터페이스 또는 기능적 특성을 사용하여 앱 컨텍스트를 얻을 수 있습니다.
객체 클래스를 만듭니다.
object CoreHelper {
lateinit var contextGetter: () -> Context
}
또는 Nullable 유형을 사용하여 더 안전하게 사용할 수 있습니다.
object CoreHelper {
var contextGetter: (() -> Context)? = null
}
앱 클래스 에서이 줄을 추가합니다.
class MyApp: Application() {
override fun onCreate() {
super.onCreate()
CoreHelper.contextGetter = {
this
}
}
}
그리고 당신의 매니페스트에서 앱 이름을 선언합니다 . MyApp
<application
android:name=".MyApp"
컨텍스트를 원할 때 간단히 전화하십시오.
CoreHelper.contextGetter()
// or if you use the nullable version
CoreHelper.contextGetter?.invoke()
도움이되기를 바랍니다.