Pertanyaan Cara statis untuk mendapatkan 'Konteks' di Android?


Apakah ada cara untuk mendapatkan arus Context contoh di dalam metode statis?

Saya mencari cara itu karena saya benci menyimpan contoh 'Konteks' setiap kali berubah.


812
2018-01-04 21:15


asal


Jawaban:


Melakukan hal ini:

Di file Manifes Android, nyatakan hal-hal berikut.

<application android:name="com.xyz.MyApplication">

</application>

Kemudian tulis kelasnya:

public class MyApplication extends Application {

    private static Context context;

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

    public static Context getAppContext() {
        return MyApplication.context;
    }
}

Sekarang di mana-mana panggilan MyApplication.getAppContext() untuk mendapatkan konteks aplikasi Anda secara statis.


1144
2018-02-25 06:37



Mayoritas aplikasi yang menginginkan metode yang nyaman untuk mendapatkan konteks aplikasi membuat kelas mereka sendiri yang meluas android.app.Application.

PANDUAN

Anda dapat melakukannya dengan terlebih dahulu membuat kelas di proyek Anda seperti berikut:

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

Kemudian, di AndroidManifest Anda, Anda harus menentukan nama kelas Anda di tag AndroidManifest.xml:

<application 
    ...
    android:name="com.example.App" >
    ...
</application>

Anda kemudian dapat mengambil konteks aplikasi dalam metode statis menggunakan berikut:

public static void someMethod() {
    Context context = App.getContext();
}

PERINGATAN

Sebelum menambahkan sesuatu seperti di atas ke proyek Anda, Anda harus mempertimbangkan apa kata dokumentasi:

Biasanya tidak perlu aplikasi subclass. Dalam kebanyakan situasi,   static singletons dapat menyediakan fungsi yang sama dalam bentuk yang lebih modular   cara. Jika Anda membutuhkan konteks global (misalnya untuk mendaftar   penerima siaran), fungsi untuk mengambilnya dapat diberikan a   Konteks yang secara internal menggunakan Context.getApplicationContext () saat   pertama membangun singleton.


REFLEKSI

Ada juga cara lain untuk mendapatkan konteks aplikasi menggunakan refleksi. Refleksi sering dipandang rendah di Android dan saya pribadi berpikir ini tidak boleh digunakan dalam produksi.

Untuk mengambil konteks aplikasi kita harus memanggil metode pada kelas tersembunyi (ActivityThread) yang telah tersedia sejak API 1:

public static Application getApplicationUsingReflection() throws Exception {
    return (Application) Class.forName("android.app.ActivityThread")
            .getMethod("currentApplication").invoke(null, (Object[]) null);
}

Ada satu lagi kelas tersembunyi (AppGlobals) yang menyediakan cara untuk mendapatkan konteks aplikasi secara statis. Itu mendapat konteks menggunakan ActivityThread jadi sebenarnya tidak ada perbedaan antara metode berikut dan yang diposting di atas:

public static Application getApplicationUsingReflection() throws Exception {
    return (Application) Class.forName("android.app.AppGlobals")
            .getMethod("getInitialApplication").invoke(null, (Object[]) null);
} 

Selamat coding!


59
2018-01-19 09:09



Tidak, saya kira tidak ada. Sayangnya, Anda terjebak panggilan getApplicationContext() dari Activity atau salah satu dari subclass lainnya Context. Juga, ini pertanyaan agak terkait.


49
2018-01-05 00:46



Ini adalah sebuah tidak terdokumentasi cara untuk mendapatkan Aplikasi (yang merupakan Konteks) dari mana saja di thread UI. Itu bergantung pada metode statis tersembunyi ActivityThread.currentApplication(). Ini harus bekerja setidaknya di 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
}

Perhatikan bahwa mungkin metode ini mengembalikan nol, mis. saat Anda memanggil metode di luar utas UI, atau aplikasi tidak terikat ke utas.

Masih lebih baik untuk digunakan @RohitGhatolsolusi jika Anda dapat mengubah kode Aplikasi.


35
2017-09-19 13:34



Itu tergantung pada apa yang Anda gunakan untuk konteks. Saya dapat memikirkan setidaknya satu kerugian pada metode itu:

Jika Anda mencoba membuat AlertDialog dengan AlertDialog.Builder, yang Application konteks tidak akan berfungsi. Saya percaya Anda membutuhkan konteks untuk saat ini Activity...


31
2017-08-12 01:07



Dengan asumsi kita berbicara tentang mendapatkan Konteks Aplikasi, saya menerapkannya seperti yang disarankan oleh @Rohit Ghatol memperluas Aplikasi. Apa yang terjadi kemudian, itu tidak ada jaminan bahwa konteks yang diambil dengan cara seperti itu akan selalu tidak nol. Pada saat Anda membutuhkannya, biasanya karena Anda ingin menginisialisasi pembantu, atau mendapatkan sumber daya, bahwa Anda tidak dapat menunda waktu; menangani kasus null tidak akan membantu Anda. Jadi saya mengerti saya pada dasarnya berjuang melawan arsitektur Android, sebagaimana tercantum dalam dokumen

Catatan: Biasanya tidak perlu aplikasi subclass. Dalam sebagian besar situasi, static singletons dapat menyediakan fungsi yang sama dengan cara yang lebih modular. Jika singleton Anda membutuhkan konteks global (misalnya untuk mendaftar penerima siaran), sertakan Context.getApplicationContext () sebagai argumen Konteks saat memanggil metode getInstance () tunggal Anda.

dan dijelaskan oleh Dianne Hackborn

Satu-satunya alasan Aplikasi ada sebagai sesuatu yang dapat Anda peroleh adalah karena selama pengembangan pra-1.0 salah satu pengembang aplikasi kami terus-menerus mengganggu saya tentang perlunya memiliki objek aplikasi tingkat atas yang dapat mereka peroleh dari sehingga mereka dapat memiliki lebih banyak "normal "kepada mereka model aplikasi, dan saya akhirnya menyerah.   Aku akan selamanya menyesal menyerah pada yang satu itu. :)

Dia juga menyarankan solusi untuk masalah ini:

Jika yang Anda inginkan adalah beberapa kondisi global yang dapat dibagikan di berbagai bagian aplikasi Anda, gunakan singleton. [...] Dan ini mengarah lebih alami ke bagaimana Anda harus mengelola hal-hal ini - menginisialisasi mereka sesuai permintaan.

jadi apa yang saya lakukan adalah menyingkirkan Aplikasi memperluas, dan menyampaikan konteks langsung ke getInstance tunggal helper (), sambil menyimpan referensi ke konteks aplikasi di konstruktor pribadi:

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

penelepon akan meneruskan konteks lokal ke helper:

Helper.getInstance(myCtx).doSomething();

Jadi, untuk menjawab pertanyaan ini dengan benar: ada cara untuk mengakses Konteks Aplikasi secara statis, tetapi mereka semua harus berkecil hati, dan Anda sebaiknya memilih menyampaikan konteks lokal ke getOnstance singleton ().


Bagi siapa pun yang tertarik, Anda dapat membaca versi yang lebih detail di blog fwd


28
2017-08-16 05:36



Jika Anda terbuka untuk digunakan RoboGuice, Anda dapat memiliki konteks disuntikkan ke kelas yang Anda inginkan. Berikut ini contoh kecil cara melakukannya dengan RoboGuice 2.0 (beta 4 pada saat penulisan ini)

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) {
        }
    }
}

11
2018-02-29 14:46



Saya telah menggunakan ini di beberapa titik:

ActivityThread at = ActivityThread.systemMain();
Context context = at.getSystemContext();

Ini adalah konteks yang valid yang saya gunakan untuk mendapatkan layanan sistem dan bekerja.

Tapi, saya menggunakannya hanya dalam rangka / modifikasi dasar dan tidak mencobanya di aplikasi Android.

SEBUAH PERINGATAN yang harus Anda ketahui: Ketika mendaftar untuk receiver siaran dengan konteks ini, itu tidak akan berfungsi dan Anda akan mendapatkan:

java.lang.SecurityException: Mengingat paket pemanggil android tidak berjalan dalam proses ProcessRecord


8
2018-05-08 10:22



Saya pikir Anda membutuhkan tubuh untuk getAppContext() metode:

public static Context getAppContext()
   return MyApplication.context; 

3
2017-08-18 14:15



Anda dapat menggunakan yang berikut:

MainActivity.this.getApplicationContext();

MainActivity.java:

...
public class MainActivity ... {
    static MainActivity ma;
...
    public void onCreate(Bundle b) {
         super...
         ma=this;
         ...

Kelas lain apa pun:

public ...
    public ANY_METHOD... {
         Context c = MainActivity.ma.getApplicationContext();

3
2018-04-06 17:25