Android এ 'প্রসঙ্গ' পেতে স্ট্যাটিক উপায়?




android-context (13)

UI থ্রেড থেকে যে কোনও জায়গা থেকে একটি developer.android.com/reference/android/app/Application.html (যা একটি প্রসঙ্গ) পেতে এখানে একটি অনথিভুক্ত উপায়। এটি লুকানো স্ট্যাটিক পদ্ধতি ActivityThread.currentApplication() Thread.current ActivityThread.currentApplication() নির্ভর করে। এটা অন্তত অ্যান্ড্রয়েড 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
}

উল্লেখ্য, এই পদ্ধতিটি নল ফিরে যাওয়ার পক্ষে সম্ভব, উদাহরণস্বরূপ, যখন আপনি UI থ্রেডের বাইরে পদ্ধতিটি কল করেন, বা অ্যাপ্লিকেশনটি থ্রেডে আবদ্ধ নয়।

@RohitGhatol এর সমাধানটি ব্যবহার করা এখনও ভাল, যদি আপনি অ্যাপ্লিকেশন কোডটি পরিবর্তন করতে পারেন।

একটি স্ট্যাটিক পদ্ধতির ভিতরে বর্তমান Context দৃষ্টান্ত পেতে একটি উপায় আছে কি?

আমি যে ভাবে খুঁজছি কারণ প্রতিবার পরিবর্তিত হলে 'কনটেক্সট' উদাহরণটি সংরক্ষণ করতে আমি ঘৃণা করি।


অনুমান করছি যে আমরা অ্যাপ্লিকেশন কনটেক্সট পাওয়ার কথা বলছি, আমি আবেদনটি প্রসারিত করে @ রোহিত ঘাতোলের প্রস্তাব অনুসারে এটি বাস্তবায়ন করেছি। এরপরে কি ঘটেছিল, এটি এমন কোন গ্যারান্টি নেই যে এই উপায়ে প্রাপ্ত প্রসঙ্গটি সর্বদা অকার্যকর হবে। আপনি যখন এটির প্রয়োজন তখন সাধারণত এটির কারণে আপনি একজন সহায়ক শুরু করতে চান, অথবা একটি সংস্থান পেতে চান, যাতে আপনি সময়মত বিলম্ব করতে পারেন না; নকল ক্ষেত্রে পরিচালনা আপনাকে সাহায্য করবে না। তাই আমি বুঝতে পেরেছিলাম যে আমি মূলত অ্যান্ড্রয়েড আর্কিটেকচারের বিরুদ্ধে যুদ্ধ করছি, যেমন ডক্সে বলা হয়েছে

দ্রষ্টব্য: অ্যাপ্লিকেশন সাবক্লাস সাধারণত প্রয়োজন নেই। বেশিরভাগ ক্ষেত্রে স্ট্যাটিক একলেটগুলি আরো মডুলার পদ্ধতিতে একই কার্যকারিতা সরবরাহ করতে পারে। আপনার সিঙ্গল্টনকে যদি গ্লোবাল প্রসঙ্গের প্রয়োজন হয় (উদাহরণস্বরূপ ব্রডকাস্ট রিসিভার নিবন্ধন করতে), আপনার একক্টন এর getInstance () পদ্ধতিটি চালানোর সময় Context.getApplicationContext () কনটেক্সট আর্গুমেন্ট হিসাবে অন্তর্ভুক্ত করুন।

এবং Dianne হ্যাকborn দ্বারা ব্যাখ্যা

একমাত্র কারণ অ্যাপ্লিকেশনটি যা আপনি অর্জন করতে পারেন তার থেকে বিদ্যমান কারণ প্রি-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();

সুতরাং, এই প্রশ্নটি সঠিকভাবে উত্তর দেওয়ার জন্য: অ্যাপ্লিকেশন কনটেক্সটটিকে স্থিরভাবে অ্যাক্সেস করার উপায় রয়েছে, তবে তাদের সকলকে নিরুৎসাহিত করা উচিত, এবং আপনাকে একক প্রসঙ্গে একক প্রবন্ধটি সিঙ্গলটনের পেতে পারেন ()।

যে কেউ আগ্রহী, আপনি fwd ব্লগে আরও বিস্তারিত সংস্করণ পড়তে পারেন


আপনি RoboGuice ব্যবহার করার জন্য খোলা RoboGuice , আপনি যে প্রসঙ্গে চান 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) {
        }
    }
}

আপনি নিম্নলিখিত ব্যবহার করতে পারেন:

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

আমি getAppContext() পদ্ধতির জন্য একটি শরীরের প্রয়োজন মনে করি:

public static Context getAppContext()
   return MyApplication.context; 

আমি এই সঙ্গে আমাকে সাহায্য করার জন্য Singleton নকশা প্যাটার্ন একটি বৈচিত্র ব্যবহার।

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 ); কল ApplicationContextSingleton.setContext( this ); আমার activity.onCreate () এবং ApplicationContextSingleton.setContext( null ); ইনডেস্ট্রয়ে () ;


আমি কেবল অ্যান্ড্রয়েডের জন্য একটি jQuery- অনুপ্রাণিত ফ্রেমওয়ার্ক প্রকাশ করেছি যা বলা হয়েছে ভ্যাপর API যা অ্যাপ ডেভেলপমেন্টকে আরও সহজ করে তুলবে।

সেন্ট্রাল $ WeakReference ক্লাসটি WeakReference (এথান নিকোলাসের দ্বারা সন্ত্রস্ত জাভা ব্লগ পোস্ট সম্পর্কিত লিঙ্ক) পরিচালনা করে যা বর্তমান Activity প্রসঙ্গে আপনি কল করে পুনরুদ্ধার করতে পারেন:

$.act()

একটি WeakReference রেফারেন্স মূল বস্তুর পুনরুদ্ধারের আবর্জনা সংগ্রহ প্রতিরোধ না করে একটি রেফারেন্স বজায় রাখে, যাতে আপনার মেমরি লিকগুলির সমস্যা হয় না।

কোর্স $.act() আপনি $.act() নাল ফিরে আসতে পারে যে ঝুঁকি চালানো হয়। আমি এখনো এই দৃশ্যকল্প জুড়ে আসতে না, যদিও, সম্ভবত এটি একটি সংক্ষিপ্ত ঝুঁকি, উল্লেখ উল্লেখযোগ্য।

আপনি যদি আপনার Activity ক্লাস হিসাবে VaporActivity ব্যবহার না করেন তবে আপনি নিজেও প্রসঙ্গটি সেট করতে পারেন:

$.act(Activity);

এছাড়াও, ভাপর এপিআই ফ্রেমওয়ার্কের বেশিরভাগই এই সংরক্ষিত প্রসঙ্গটিকে অন্তর্নিহিতভাবে ব্যবহার করে, যার অর্থ আপনি যদি ফ্রেমওয়ার্কটি ব্যবহার করার সিদ্ধান্ত নিচ্ছেন তবে আপনাকে এটি নিজেও সংরক্ষণ করতে হবে না। আরো তথ্য এবং নমুনা জন্য সাইট দেখুন।

আমি আশা করি এটি সাহায্য করবে :)


এটা আপনি প্রসঙ্গ ব্যবহার করছেন কি উপর নির্ভর করে। আমি যে পদ্ধতির অন্তত একটি অসুবিধা মনে করতে পারেন:

আপনি যদি AlertDialog সাথে একটি AlertDialog তৈরি করার চেষ্টা করছেন তবে Application প্রসঙ্গটি কাজ করবে না। আমি বিশ্বাস করি আপনি বর্তমান Activity জন্য প্রসঙ্গ প্রয়োজন ...


তাই আমি গৃহীত উত্তরটি সংশোধন করেছি কারণ এটি একটি মেমরি লিক সৃষ্টি করে, আমি যা দিয়ে এসেছি ...

Andro আইডি

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

আমি আসলে যা করেছি তা হল, একটি বস্তুর প্রসঙ্গ উল্লেখ করুন এবং বস্তুর প্রসঙ্গ হিসাবে উপস্থাপন করুন (প্রসঙ্গে তা নিক্ষেপ করুন)। এটা সাহায্য আশা করি।


না, আমি মনে করি না। দুর্ভাগ্যবশত, আপনি Activity থেকে বা Context অন্য উপশ্রেণীগুলির একটিতে getApplicationContext() কলিং আটকে আছেন। এছাড়াও, this প্রশ্নটি কিছুটা সম্পর্কিত।


রোহিতের উত্তর সঠিক বলে মনে হচ্ছে। তবে, সচেতন থাকুন যে অ্যান্ড্রয়েড স্টুডিওর "ইনস্ট্যান্ট রান" আপনার কোডে static Context বৈশিষ্ট্যগুলি থাকার উপর নির্ভর করে, যতদূর আমি জানি।


এই উত্স অনুসারে আপনি কনটেক্সটপ্রেপার প্রসারিত করে নিজের কনটেক্সট পেতে পারেন

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

ContextWrapper জন্য জাভাডোক

Context প্রক্সি বাস্তবায়ন যে কেবল অন্য কনটেক্সট তার কল সব delegates। মূল প্রসঙ্গ পরিবর্তন ছাড়া আচরণ পরিবর্তন করতে subclassed করা যেতে পারে।


কোটলিন পথ :

সুস্পষ্ট:

<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 মাধ্যমে সম্পত্তি অ্যাক্সেস করতে পারেন





android-context