ما الفرق بين أساليب مختلفة للحصول على السياق ؟

StackOverflow https://stackoverflow.com/questions/1026973

  •  06-07-2019
  •  | 
  •  

سؤال

في مختلف أجزاء الروبوت رمز رأيت:

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

ولكن أنا لا يمكن العثور على أي لائقة التفسير الذي هو الأفضل ، وتحت أي ظرف من الظروف التي ينبغي استخدامها.

مؤشرات إلى الوثائق على هذا التوجيه حول ما قد كسر لو خطأ واحد هو المختار ، سيكون محل تقدير كبير.

هل كانت مفيدة؟

المحلول

وأوافق على أن ثائق نادرة عندما يتعلق الأمر سياقات في الروبوت، ولكن يمكنك تجميع بعض الحقائق من مصادر مختلفة.

هذا بلوق وظيفة على جوجل الروبوت الرسمي وقد كتب مطوري بلوق معظمهم للمساعدة في تسرب الذاكرة عنوان، ولكنها توفر بعض المعلومات الجيدة عن السياقات أيضا:

<اقتباس فقرة>   

في تطبيق الروبوت العادية، كنت   وعادة ما يكون نوعين من السياق،   آخر والتطبيق.

وقراءة المقال يقول قليلا أبعد عن الفرق بين الاثنين وعندما قد ترغب في النظر في استخدام سياق التطبيق (Activity.getApplicationContext()) بدلا من استخدام آخر إطار this). في الأساس يرتبط سياق التطبيق مع تطبيق وسوف يكون دائما هو نفسه في جميع أنحاء دورة حياة التطبيق الخاص بك، حيث كما يرتبط سياق آخر مع النشاط وربما يمكن أن يتم تدميرها عدة مرات كما يتم تدمير النشاط خلال التغييرات اتجاه الشاشة و على هذا الأساس.

وأنا لا يمكن أن تجد أي شيء حقا حول وقت استخدام getBaseContext () وغيرها من وظيفة من ديان Hackborn، واحدة من مهندسي غوغل تعمل على SDK الروبوت:

<اقتباس فقرة>   

لا تستخدم getBaseContext ()، ومجرد استخدام   سياق لديك.

وكان ذلك من وظيفة على في المطورين الروبوت أخبار ، قد ترغب في النظر في طلب سؤالك هناك أيضا، لأن حفنة من الناس الذين يعملون على جهاز الروبوت الفعلي الذي الأخبار والإجابة على الأسئلة.

وهكذا عموما يبدو أفضل من استخدام سياق التطبيق العالمي عندما يكون ذلك ممكنا.

نصائح أخرى

هذا ما وجدته فيما يتعلق باستخدام 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() كما هذا السياق توجد عمر من التطبيق.

استرداد اسم الروبوت الحالية الحزمة:

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) . المستمعين و نوع آخر من الروبوت الطبقات (مثلا ، 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 (بما في ذلك inlined/جزءا لا يتجزأ من المتلقي), استخدام جهاز الاستقبال الخاصة السياق.

الخارجية 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);
        }
    }
}

Inlined/جزءا لا يتجزأ من 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() كما نصحت من قبل الروبوت إطار المطورين.

تحديث: إضافة أمثلة 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);

ما لاحظت:إذا كنت مثيل الخاص بك linearLayout مع applicationContext ، ثم عند النقر على زر الزيادة والنقصان في النشاط الخاص بك, سيكون لديك غير مسك استثناء ، قادمة من dalvik virtual machine (ليس من التعليمات البرمجية الخاصة بك, هذا هو السبب في أنني قد قضيت الكثير من الوقت للعثور حيث كان خطأي...).

إذا كنت تستخدم baseContext, ثم وهذا هو كل الحق ، قائمة السياق سيتم فتح سوف تكون قادرة على الاختيار من بين الخيارات الخاصة بك.

حتى هنا هو بلدي الختام:أعتقد (أنا لم تختبر كذلك) من baseContext مطلوب عند التعامل مع contextMenu في النشاط الخاص بك...

الاختبار تم القيام به الترميز مع API 8, اختبارها على HTC Desire, android 2.3.3.

أتمنى تعليقي قد لا تشعر بالملل حتى الآن, وأتمنى لك كل خير.سعيد الترميز ;-)

أولا، أنا أوافق على أننا يجب أن تستخدم appcontext كلما أمكن ذلك. ثم "هذا" في النشاط. أنا لم أصب الحاجة إلى basecontext.

في بلدي التجارب، في معظم الحالات، يمكن أن يكون متبادل. في معظم الحالات، والسبب كنت ترغب في الحصول على عقد من السياق هو الوصول إلى الملفات، والأفضليات، قاعدة البيانات وما إلى ذلك تنعكس هذه البيانات في نهاية المطاف على شكل ملفات في مجلد البيانات الخاصة التطبيق الخاص بك (/ بيانات / بيانات /). بغض النظر عن السياق الذي تستخدمه، وأنها سوف يتم تعيينها إلى نفس المجلد / الملفات بحيث كنت موافق.

وهذا ما لاحظته. ربما هناك حالات يجب التمييز بينها.

في بعض الحالات قد تستخدم سياق آخر على سياق التطبيق عند تشغيل شيء في الموضوع. عند اكتمال موضوع التنفيذ وتحتاج إلى إرجاع النتيجة إلى النشاط المتصل، تحتاج هذا السياق مع معالج.

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

في كلمات بسيطة

وgetApplicationContext() كاسم طريقة توحي سيجعل التطبيق على بينة من تطبيق تفاصيل واسعة والتي يمكنك الوصول إليها من أي مكان في التطبيق. حتى تتمكن من الاستفادة من هذه الخدمة في ملزمة، تسجيل بث الخ Application context سوف يكون على قيد الحياة حتى مخارج التطبيق.

وgetActivity() أو this سيجعل التطبيق على بينة من الشاشة الحالية وهو أمر واضح أيضا تفاصيل مستوى التطبيق التي تقدمها application context. لذلك كل ما تريد أن تعرفه عن الشاشة الحالية مثل Window ActionBar Fragementmanger وتتوفر حتى مع هذا السياق. في الأساس وActivity تمديد Context. هذا السياق سوف قيد الحياة حتى المكون الحالي (النشاط) على قيد الحياة

ولقد استعملت فقط هذا وgetBaseContext عندما شرب نخب من onClick (جدا مستجد الأخضر لكلا جافا والروبوت). أنا استخدم هذا عندما بلدي الفرس مباشرة في النشاط ويضطرون إلى استخدام getBaseContext في الفرس الداخلي مجهول. انا التخمين ان هو الى حد كبير خدعة مع getBaseContext، فإنه ربما يعود سياق النشاط الذي الطبقة الداخلية يختبئ.

الارتباك ينبع من حقيقة أن هناك العديد من الطرق الوصول السياق ، مع (على السطح) أي اختلافات ملحوظة.وفيما يلي أربعة من أكثر الطرق شيوعا كنت قد تكون قادرة على الوصول إلى السياق في النشاط.

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

ما هو السياق ؟ أنا شخصيا أحب أن أفكر في سياق حالة التطبيق الخاص بك في أي وقت.تطبيق السياق يمثل العالمية أو تكوين قاعدة من التطبيق الخاص بك و نشاط أو خدمة يمكن البناء عليها ويمثل تكوين مثيل التطبيق الخاص بك أو متعدية منه.

إذا كنت تبحث في مصدر اندرويد.محتوى.السياق ، ترى أن السياق هو خلاصة الدرجة التعليقات على فئة كما يلي:

واجهة المعلومات العالمية حول تطبيق البيئة.هذا هو خلاصة الدرجة التي يتم توفيرها من قبل نظام أندرويد.ذلك يسمح بالوصول إلى application-specific الموارد والطبقات ، وكذلك ما يصل يدعو application-level عمليات مثل إطلاق أنشطة البث وتلقي النوايا ، إلخ.ما يسلب من هذا هو أن السياق يقدم المشتركة تنفيذ للوصول إلى مستوى التطبيق وكذلك نظام مستوى الموارد.تطبيق مستوى الموارد قد يكون الوصول إلى أشياء مثل سلسلة الموارد [getResources()] أو الأصول [getAssets()] وعلى مستوى النظام الموارد هو شيء التي يمكنك الوصول إليها مع Context.getSystemService().

كما واقع الأمر ، نلقي نظرة على التعليقات على أساليب يبدو إلى تعزيز هذا المفهوم:

getSystemService():عودة المؤشر إلى system-level خدمة بالاسم.فئة الكائن عاد يختلف حسب الاسم المطلوب.getResources():العودة الموارد سبيل المثال التطبيق الخاص بك حزمة.getAssets():العودة الموارد سبيل المثال التطبيق الخاص بك حزمة.قد يكون من المفيد الإشارة إلى أنه في سياق فئة مجردة ، كل من الأساليب المذكورة أعلاه هي مجردة!مثيل واحد فقط من getSystemService(الطبقة) وقد التنفيذ التي تحتج طريقة مجردة.وهذا يعني تنفيذ هذه يجب أن تكون المقدمة في الغالب قبل تنفيذ فصول ، والتي تشمل:

ContextWrapper
Application
Activity
Service
IntentService

النظر في وثائق API الهرمي من الطبقات تبدو مثل هذا:

السياق

| — ContextWrapper

|— — تطبيق

| — — ContextThemeWrapper

|— — — — النشاط

| — — خدمة

|— — — IntentService

لأننا نعلم أن Context نفسها لا تقدم أي فكرة ننتقل إلى الشجرة و نلقي نظرة على ContextWrapper وندرك أن ليس هناك الكثير أيضا.منذ تطبيق يمتد ContextWrapper, ليس كثيرا أن ننظر إلى هناك إما لأنه لا تجاوز التنفيذ المقدمة من ContextWrapper.وهذا يعني أن تنفيذ هذا السياق يتم توفيرها من قبل نظام التشغيل و هو مخفي من API.يمكنك أن تأخذ نظرة على التنفيذ الملموس السياق من خلال النظر في مصدر ContextImpl الدرجة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top