source

어디에서나 애플리케이션 컨텍스트를 사용하고 계십니까?

nicesource 2023. 6. 3. 08:30
반응형

어디에서나 애플리케이션 컨텍스트를 사용하고 계십니까?

Android 앱에서 다음과 같은 접근 방식에 문제가 있습니까?

public class MyApp extends android.app.Application {

    private static MyApp instance;

    public MyApp() {
        instance = this;
    }

    public static Context getContext() {
        return instance;
    }

}

컨텍스트가 필요한 모든 곳(예: SQLiteOpenHelper)에 전달할 수 있습니까(물론 유출되지는 않습니까)?

이 접근 방식에는 몇 가지 잠재적인 문제가 있습니다. (예를 들어) 많은 상황에서 잘 작동합니다.

특히 가 필요한 문제를 처리할 때는 주의해야 합니다. 예를 들어 응용 프로그램 컨텍스트를 에 전달하면 예외가 발생합니다.일반적으로 사용자의 접근 방식은 훌륭합니다. 메모리 누수를 방지하기 위해 의 범위를 벗어나는 컨텍스트를 전달할 때는 이 내에서Context 를 사용하는 것이 좋습니다.

또한 패턴의 대안으로 호출의 바로 가기를 사용할 수 있습니다.getApplicationContext()개체(예: 활동)에서 응용프로그램 컨텍스트를 가져옵니다.

제 경험상 이 접근법은 필요하지 않습니다.컨텍스트가 필요한 경우 일반적으로 View.getContext()전화를 걸어 다음을 사용하여 컨텍스트를 얻을 수 있습니다.Context여기서 얻은 정보를 사용하여 Context.getApplicationContext()호출하여Application맥락.만약 당신이 그것을 얻으려고 한다면,Application문맥에 따라 이것을.Activity당신은 항상 Activity.getApplication()을 호출할 수 있습니다. 이것은 다음과 같이 전달될 수 있어야 합니다.Context로의 통화에 필요한SQLiteOpenHelper().

전반적으로 이 상황에 대한 당신의 접근 방식에는 문제가 없는 것처럼 보이지만, 처리할 때.ContextGoogle Android Developers 공식 블로그에 설명된 대로 메모리가 어디에도 유출되지 않도록 하십시오.

일부 사람들은 싱글톤이 어떻게 널 포인터를 반환할 수 있는지 물었습니다.저는 그 질문에 답하고 있습니다.(코드를 올려야 해서 댓글로 답변할 수 없습니다.)

(1) 클래스가 로드되고 (2) 이 클래스의 개체가 생성되는 두 이벤트 사이에 null을 반환할 수 있습니다.다음은 예입니다.

class X {
    static X xinstance;
    static Y yinstance = Y.yinstance;
    X() {xinstance=this;}
}
class Y {
    static X xinstance = X.xinstance;
    static Y yinstance;
    Y() {yinstance=this;}
}

public class A {
    public static void main(String[] p) {
    X x = new X();
    Y y = new Y();
    System.out.println("x:"+X.xinstance+" y:"+Y.yinstance);
    System.out.println("x:"+Y.xinstance+" y:"+X.yinstance);
    }
}

코드를 실행합니다.

$ javac A.java 
$ java A
x:X@a63599 y:Y@9036e
x:null y:null

두 번째 줄은 Y.x 인스턴스 및 X.y 인스턴스가 null임나타냅니다. X.x 인스턴스 및 Y.y 인스턴스 변수가 null일 때 읽혔기 때문에 이러한 인스턴스는 null입니다.

이것은 고칠 수 있습니까?네.

class X {
    static Y y = Y.getInstance();
    static X theinstance;
    static X getInstance() {if(theinstance==null) {theinstance = new X();} return theinstance;}
}
class Y {
    static X x = X.getInstance();
    static Y theinstance;
    static Y getInstance() {if(theinstance==null) {theinstance = new Y();} return theinstance;}
}

public class A {
    public static void main(String[] p) {
    System.out.println("x:"+X.getInstance()+" y:"+Y.getInstance());
    System.out.println("x:"+Y.x+" y:"+X.y);
    }
}

이 코드는 이상이 없습니다.

$ javac A.java 
$ java A
x:X@1c059f6 y:Y@152506e
x:X@1c059f6 y:Y@152506e

하지만 이것은 Android를 위한 옵션이 아닙니다.Application. object: 그래머는생시제않간습다니지어하.

다시 한 번 말하지만, 첫 번째 예제와 두 번째 예제의 차이점은 정적 포인터가 null인 경우 두 번째 예제가 인스턴스를 만든다는 것입니다.그러나 프로그래머는 시스템이 결정하기 전에 안드로이드 응용 프로그램 개체를 만들 수 없습니다.

갱신하다

하는 또 는 화된정필발는하또생다다곤운같예니습다는초음과기러혹스른적드가▁one▁where▁happen입니다.null.

Main.java:

enum MyEnum {
    FIRST,SECOND;
    private static String prefix="<", suffix=">";
    String myName;
    MyEnum() {
        myName = makeMyName();
    }
    String makeMyName() {
        return prefix + name() + suffix;
    }
    String getMyName() {
        return myName;
    }
}
public class Main {
    public static void main(String args[]) {
        System.out.println("first: "+MyEnum.FIRST+" second: "+MyEnum.SECOND);
        System.out.println("first: "+MyEnum.FIRST.makeMyName()+" second: "+MyEnum.SECOND.makeMyName());
        System.out.println("first: "+MyEnum.FIRST.getMyName()+" second: "+MyEnum.SECOND.getMyName());
    }
}

그러면 다음과 같은 이점을 얻을 수:

$ javac Main.java
$ java Main
first: FIRST second: SECOND
first: <FIRST> second: <SECOND>
first: nullFIRSTnull second: nullSECONDnull

정적 변수 선언을 한 줄 위로 이동할 수 없습니다. 코드가 컴파일되지 않습니다.

응용 프로그램 클래스:

import android.app.Application;
import android.content.Context;

public class MyApplication extends Application {

    private static Context mContext;

    public void onCreate() {
        super.onCreate();
        mContext = getApplicationContext();
    }

    public static Context getAppContext() {
        return mContext;
    }

}

Android Manifest에서 응용 프로그램 선언:

<application android:name=".MyApplication"
    ...
/>

용도:

MyApplication.getAppContext()

위해 " 용프로램컨를가응위가래생해성하고려는하데있다습"를.null포인터

제가 알기로는, 두 가지 중 하나라도 전화를 하는 것이 더 나은 접근법인 것 같습니다.Context.getApplicationContext()또는Activity.getApplication().

그것은 좋은 접근법입니다.제가 직접 사용하기도 사용하기도 합니다.제가 제안하고 싶은 것은 단지onCreate생성자를 사용하는 대신 싱글톤을 설정합니다.

이 그고당신언이급이후로한리▁you이로후▁mentioned▁and▁since.SQLiteOpenHelperonCreate ()데이터베이스도 열 수 있습니다.

개인적으로 저는 문서가 "일반적으로 애플리케이션을 하위 분류할 필요가 없습니다"라고 말하는 것이 잘못되었다고 생각합니다.저는 그 반대가 사실이라고 생각합니다.응용프로그램을 항상 하위 클래스로 분류해야 합니다.

생성자에서 시스템 서비스를 얻기 위해 응용프로그램 컨텍스트를 사용합니다.이는 테스트를 용이하게 하고 구성의 이점을 제공합니다.

public class MyActivity extends Activity {

    private final NotificationManager notificationManager;

    public MyActivity() {
       this(MyApp.getContext().getSystemService(NOTIFICATION_SERVICE));
    }

    public MyActivity(NotificationManager notificationManager) {
       this.notificationManager = notificationManager;
    }

    // onCreate etc

}

그러면 테스트 클래스에서 오버로드된 생성자를 사용합니다.

Android는 기본 생성자를 사용합니다.

저는 그것을 좋아하지만, 대신 싱글톤을 제안하고 싶습니다.

package com.mobidrone;

import android.app.Application;
import android.content.Context;

public class ApplicationContext extends Application
{
    private static ApplicationContext instance = null;

    private ApplicationContext()
    {
        instance = this;
    }

    public static Context getInstance()
    {
        if (null == instance)
        {
            instance = new ApplicationContext();
        }

        return instance;
    }
}

저도 같은 접근법을 사용하고 있습니다. 싱글톤을 조금 더 잘 쓸 것을 제안합니다.

public static MyApp getInstance() {

    if (instance == null) {
        synchronized (MyApp.class) {
            if (instance == null) {
                instance = new MyApp ();
            }
        }
    }

    return instance;
}

하지만 모든 곳을 사용하는 것은 아닙니다.getContext()그리고.getApplicationContext()내가 할 수 있는 곳에!

저는 원래 질문이 13년 전에 게시되었다는 것을 알고 있습니다. 그리고 이것은 모든 곳에서 상황을 파악하는 코틀린 버전입니다.

class MyApplication : Application() {
    companion object {
        @JvmStatic
        private var instance: MyApplication? = null

        @JvmStatic
        public final fun getContext(): Context? {
            return instance
        }
    }

    override fun onCreate() {
        instance = this
        super.onCreate()
    }
}

언급URL : https://stackoverflow.com/questions/987072/using-application-context-everywhere

반응형