অ্যান্ড্রয়েডে 'প্রসঙ্গ' পাওয়ার স্ট্যাটিক উপায়?


970

Contextস্ট্যাটিক পদ্ধতিতে বর্তমান উদাহরণটি পাওয়ার কোনও উপায় আছে কি ?

আমি সেভাবে সন্ধান করছি কারণ প্রতিবার পরিবর্তিত পরিবর্তনের সাথে 'প্রসঙ্গটি' সংরক্ষণ করা আমি ঘৃণা করি।


57
কনটেক্সট সংরক্ষণ না করা একটি ভাল ধারণাটি কেবল অসুবিধাগুলির কারণে নয়, তবে আরও বেশি কারণ এটি বিশাল মেমরি ফাঁস হতে পারে!
বিক্রম বডিচেরলা

12
@ ভিক্রমডোডিচরলা হ্যাঁ, তবে নীচের উত্তরগুলি ধরে নেওয়া যায় যে আমরা আবেদনের প্রসঙ্গে বলছি। সুতরাং, মেমরি ফাঁস কোনও সমস্যা নয়, তবে ব্যবহারকারীর কেবলমাত্র এই সমাধানগুলি ব্যবহার করা উচিত যেখানে এটি ব্যবহারের সঠিক প্রসঙ্গ।
টম

যদি আপনাকে পাওয়ার স্থিতিশীল উপায় ব্যবহার Contextকরতে হয় তবে কোডটি ডিজাইনের আরও ভাল উপায় হতে পারে।
20:48

3
অ্যান্ড্রয়েড ডকুমেন্টেশনগুলি সিঙ্গেলটনের গ্রাহকদের কাছে প্রসঙ্গটি পাস করার পরামর্শ দেয়। developer.android.com/references/android/app/Application.html
মার্কো লুগলিও

Singletons এবং প্রসঙ্গ getInstance () স্ট্যাটিক প্রসঙ্গ ধরে পাস করা উচিত ছিল জন্য, দয়া করে, একটি চেহারা আছে আমি আমার যুক্তি ব্যাখ্যা করার চেষ্টা করে এখানে কাজ কোড সহ সমর্থিত: stackoverflow.com/a/38967293/4469112
Alessio

উত্তর:


1302

এটা কর:

অ্যান্ড্রয়েড ম্যানিফেস্ট ফাইলে নিম্নলিখিতগুলি ঘোষণা করুন।

<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() আপনার অ্যাপ্লিকেশন প্রসঙ্গটি স্থিতিশীলভাবে পেতে ।


81
এই পদ্ধতির কোনও ক্ষতি আছে কি? এই প্রতারণার মত মনে হচ্ছে। (একটি হ্যাক?)
jjnguy

203
নেতিবাচক দিকটি হ'ল কোনও স্ট্যাটিক ইনিশিয়েশন কোড আপনার কনটেক্সট অবজেক্ট আনার চেষ্টা করার আগে নন-স্ট্যাটিক অনক্রিয়েট () কল করা হবে এমন কোনও গ্যারান্টি নেই। তার মানে আপনার কলিং কোডটি নাল মানগুলি নিয়ে কাজ করার জন্য প্রস্তুত হতে হবে যা এই প্রশ্নের পুরো বিন্দুকে হারাতে পারে।
মেলিন্ডা সবুজ

8
এছাড়াও হতে পারে .. আমরা এই static contextপরিবর্তনশীল হিসাবে ঘোষণা করা উচিত volatile?
ভ্লাদিমির সোরোকিন

14
@ টম এটি কোনও স্ট্যাটিক ডেটা সদস্যের প্রাথমিকভাবে স্ট্যাটিকভাবে হওয়ার ঘটনা নয়। প্রদত্ত কোডে, স্থিতিশীল সদস্যটি অনক্রিট () এ অ-স্থিতিশীলভাবে শুরু করা হচ্ছে। এমনকি স্ট্যাটিক্যালি আর্কিটাইজড ডেটাও এই ক্ষেত্রে যথেষ্ট ভাল না কারণ কোনও কিছু নিশ্চিত করে না যে প্রদত্ত শ্রেণীর স্ট্যাটিক সূচনাটি অন্য কোনও শ্রেণির স্ট্যাটিক ইনিশিয়েশনের সময় অ্যাক্সেস করার আগেই ঘটবে।
মেলিন্ডা সবুজ

10
@ মেলিন্ডগ্রাইন অ্যাপ্লিকেশনটির ডকুমেন্টেশন অনুসারে, কোনও ক্রিয়াকলাপ, পরিষেবা বা রিসিভার (সামগ্রী সরবরাহকারী ব্যতীত) তৈরি হওয়ার আগে অনক্রিট () কল করা হয়। সুতরাং আপনি যদি কোনও সামগ্রী সরবরাহকারী থেকে getAppContext () অ্যাক্সেস করার চেষ্টা না করেন ততক্ষণ এই সমাধানটি নিরাপদ হবে না?
ম্যাগনাস ডব্লু

86

অ্যাপ্লিকেশন প্রসঙ্গটি পেতে একটি সুবিধাজনক পদ্ধতি চায় এমন বেশিরভাগ অ্যাপ্লিকেশন তাদের নিজস্ব বর্গ তৈরি করে যা প্রসারিত 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;
    }
}

তারপরে, আপনার অ্যান্ড্রয়েড ম্যানিফেস্টে আপনার নিজের শ্রেণীর নাম অ্যান্ড্রয়েড ম্যানিফেস্ট.এক্সএমএল ট্যাগটিতে উল্লেখ করা উচিত:

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

তারপরে আপনি নিম্নলিখিতটি ব্যবহার করে কোনও স্থিতিশীল পদ্ধতিতে অ্যাপ্লিকেশন প্রসঙ্গটি পুনরুদ্ধার করতে পারেন:

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

সতর্কতামূলক

আপনার প্রকল্পে উপরের মতো কিছু যুক্ত করার আগে আপনার ডকুমেন্টেশন কী বলে তা বিবেচনা করা উচিত:

সাধারণত সাবক্লাস অ্যাপ্লিকেশন প্রয়োজন হয় না। বেশিরভাগ পরিস্থিতিতে স্থিতিশীল সিঙ্গলেটগুলি আরও কার্যকরভাবে একই কার্যকারিতা সরবরাহ করতে পারে। যদি আপনার সিঙ্গলটনের কোনও বৈশ্বিক প্রসঙ্গের প্রয়োজন হয় (উদাহরণস্বরূপ ব্রডকাস্ট রিসিভারগুলি নিবন্ধ করার জন্য), এটি পুনরুদ্ধার করার জন্য ফাংশনটি এমন একটি প্রবন্ধ দেওয়া যেতে পারে যা সিঙ্গলটন নির্মাণের সময় অভ্যন্তরীণভাবে Context.get ApplicationContext () ব্যবহার করে।


প্রতিফলন

প্রতিবিম্ব ব্যবহার করে অ্যাপ্লিকেশন প্রসঙ্গটি পাওয়ার আরও একটি উপায় রয়েছে। অ্যান্ড্রয়েডে প্রায়শই প্রতিবিম্বকে তুচ্ছ করা হয় এবং আমি ব্যক্তিগতভাবে মনে করি এটি উত্পাদন ক্ষেত্রে ব্যবহার করা উচিত নয়।

অ্যাপ্লিকেশন প্রসঙ্গটি পুনরুদ্ধার করতে আমাদের অবশ্যই একটি লুকানো শ্রেণিতে ( ক্রিয়াকলাপ ) যা একটি এপিআই 1 থেকে পাওয়া যায় তার জন্য একটি পদ্ধতির আবেদন করতে হবে :

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

এখানে আরও একটি গোপন শ্রেণি রয়েছে ( অ্যাপ্লিক্লাবলস ) যা স্থিতিশীল উপায়ে অ্যাপ্লিকেশন প্রসঙ্গটি পাওয়ার জন্য একটি উপায় সরবরাহ করে। এটি ব্যবহার করে প্রসঙ্গটি পাওয়া যায় ActivityThreadতাই নিম্নলিখিত পদ্ধতি এবং উপরের পোস্টের মধ্যে সত্যিকারের কোনও পার্থক্য নেই:

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

শুভ কোডিং!


56

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

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

এবং ব্যাখ্যা দিয়েছিলেন ডায়ান হ্যাকোবার

অ্যাপ্লিকেশনটি আপনি যে কিছু থেকে উদ্ভব করতে পারেন সে হিসাবে উপস্থিত থাকার একমাত্র কারণ হ'ল আমাদের অ্যাপ্লিকেশন বিকাশকারী প্রাক -১.০ বিকাশের সময় ক্রমাগত আমাকে একটি উচ্চ স্তরের অ্যাপ্লিকেশন অবজেক্ট যা তারা পেতে পারে সে সম্পর্কে প্রয়োজনীয়ভাবে বাগডাগুলি করছিল যাতে তারা আরও "স্বাভাবিক" থাকতে পারে "তাদের কাছে অ্যাপ্লিকেশন মডেল, এবং আমি শেষ পর্যন্ত দিয়েছি that সেইটিতে দেওয়ার জন্য আমি চিরকালের জন্য অনুশোচনা করব। :)

তিনি এই সমস্যার সমাধানের পরামর্শও দিচ্ছেন:

আপনি যদি চান এমন কিছু বিশ্বব্যাপী রাষ্ট্র যা আপনার অ্যাপের বিভিন্ন অংশে ভাগ করা যায় তবে একটি সিঙ্গলটন ব্যবহার করুন। [...] এবং এটি আপনাকে স্বাভাবিকভাবে কীভাবে এই জিনিসগুলি পরিচালনা করা উচিত - চাহিদা অনুযায়ী সেগুলি সূচনা করার দিকে পরিচালিত করে।

তাই আমি যা করেছি তা অ্যাপ্লিকেশন বাড়ানো থেকে মুক্তি পেয়েছিল এবং প্রাইভেট কনস্ট্রাক্টরে অ্যাপ্লিকেশন প্রসঙ্গে একটি রেফারেন্স সংরক্ষণ করার সময় প্রসঙ্গটি সরাসরি সিঙ্গেলটন হেল্পারের 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 ব্লগে আরও বিস্তারিত সংস্করণ পড়তে পারেন


1
@ অ্যালেসিও কি এই পদ্ধতিটির ফলে মেমরি ফাঁস হয় না
ফিলিপ কিগেনি

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

1
আমি মনে করি @ কিগেনিফিলিপটি সঠিক, এবং এটি এখনও একটি উত্স ফাঁসের প্রতিনিধিত্ব করে। আপনার প্রথম কল করার পরে রেফারেন্স চার্টটি চিত্র করুন getInstance(ctx)। আপনার instanceটাইপের একটি জিসি মূল রয়েছে MyHelper, যার প্রকারের একটি ব্যক্তিগত ক্ষেত্র mContextরয়েছে Context, যা প্রসঙ্গে প্রেরণের মাধ্যমে সংগৃহীত অ্যাপ্লিকেশন প্রসঙ্গটি উল্লেখ করে getInstance()instanceকখনই দ্বিতীয়বার সেট করা হয় না বা সাফ হয় না, তাই জিসি কখনই অ্যাপ্লিকেশনটি রেফারেন্স করবে না instance। আপনি কোনও কার্যক্রম ফাঁস করবেন না যাতে এটি কম দামের আইএমও হয়।
মার্ক ম্যাকেন্না

1
@ মার্কম্যাককেইনা আপনার বিবরণ হিসাবে "যেটিতে একটি প্রাইভেট ফিল্ডের এমকন্টেক্সট টাইপ কনটেক্সট রয়েছে, যা অ্যাপ্লিকেশন প্রসঙ্গে উল্লেখ করে", সুতরাং আপনার কাছে এটি স্পষ্ট যে এমকনটেক্সট কোনও প্রসঙ্গে নয়, অ্যাপ্লিকেশন প্রসঙ্গে একটি রেফারেন্স। ইন getApplicationContext () ডক্স আপনি পড়তে: "একটি কনটেক্সট যার জীবনচক্র বর্তমান প্রসঙ্গ, প্রক্রিয়া বদলে বর্তমান উপাদানের জীবনকাল আবদ্ধ থাকে তা থেকে পৃথক হয়"। এটি কীভাবে মেমরি ফুটো তৈরি করতে পারে? প্রক্রিয়াটি প্রস্থান হলেই আবেদনের প্রসঙ্গটি GC'd হয়।
আলেসিও

1
@Alessio যদি আপনি গ্রহণ যে আবেদন প্রেক্ষাপটে একটি রেফারেন্স একটি সম্পদ লিক হিসাবে বিবেচিত হবে না, তাহলে আপনি এই একটি স্ট্যাটিক রেফারেন্স পোস্ট করে প্রক্রিয়া সহজ করতে thisApplication.onCreate()যা গৃহীত উত্তর ভাল করে।
মার্ক ম্যাকেন্না

49

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


8
নিবন্ধটির ডান লিংক: android-developers.blogspot.co.il/2009/01/…
তাল ওয়েইস

38

ইউআই থ্রেডের যে কোনও জায়গা থেকে কোনও অ্যাপ্লিকেশন (যা একটি প্রসঙ্গ) পাওয়ার জন্য এখানে একটি অনথিভুক্ত উপায় । এটি লুকানো স্থির পদ্ধতির উপর নির্ভর করে । এটি কমপক্ষে Android 4.x এ কাজ করা উচিত xActivityThread.currentApplication()

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
}

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

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


1
আমি উপরের পদ্ধতিটি কেনেটিএম ব্যবহার করেছি তবে কখনও কখনও পদ্ধতিটি শূন্য হয়। এর বিকল্প আছে কি? আমরা যদি এখানে কোনও শূন্য পেতে পারি তবে আমরা অন্য কোথাও থেকে প্রসঙ্গটি পুনরুদ্ধার করতে পারি। আমার ক্ষেত্রে, প্রয়োগের অনক্রিট () কল করা হয়নি। তবে উপরোক্ত পদ্ধতিটি এর আগে ডেকে আনে। Plzzz সহায়তা
অ্যান্ড্রয়েডগুই

এটি সর্বদা সেই ক্ষেত্রে কার্যকর হবে না যেখানে জিসি সমস্ত ক্রিয়াকলাপ সম্পর্কিত সমস্ত জিনিস পরিষ্কার করে দিয়েছে।
অ্যালেক্সভিপার্ল

32

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

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


6
সেটা ঠিক. আপনি যদি এর জন্য অ্যাপ্লিকেশন প্রসঙ্গটি ব্যবহার করেন তবে আপনি আপনার ডায়ালগটি অগ্রভাগের ক্রিয়াকলাপের আড়ালে দেখতে পাবেন।
Nate

3
সবার আগে +1। এবং যে সম্ভাব্য ত্রুটিটি আসে তা ক্রিয়াকলাপটি শুরু করতে অক্ষম হয় কম্পোনেন্টআইনফো {com.sample / com.MyActivity}: android.view.WindowManager $ BadTokenException: উইন্ডো যুক্ত করতে অক্ষম - টোকেন নাল কোনও অ্যাপ্লিকেশনের জন্য নয়
গোবিন্দ

15

কোটলিন পথ :

সুস্পষ্ট:

<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


11

আপনি যদি রোবুইস ব্যবহারের জন্য উন্মুক্ত হন , আপনি চান এমন কোনও শ্রেণিতে প্রসঙ্গটি ইনজেকশন করতে পারেন। রোবুইস ২.০ দিয়ে কীভাবে এটি করা যায় তার একটি ছোট নমুনা এখানে (এই লেখার সময় বিটা 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) {
        }
    }
}

8

আমি এটি এক পর্যায়ে ব্যবহার করেছি:

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

এটি একটি বৈধ প্রসঙ্গ যা আমি সিস্টেম পরিষেবা পেতে এবং কাজ করতে ব্যবহার করি।

তবে, আমি এটি কেবল ফ্রেমওয়ার্ক / বেস পরিবর্তনগুলিতে ব্যবহার করেছি এবং অ্যান্ড্রয়েড অ্যাপ্লিকেশনগুলিতে এটি চেষ্টা করি নি।

একটি সতর্কতা যা আপনাকে অবশ্যই জানতে হবে: যখন এই প্রসঙ্গে সম্প্রচারিত রিসিভারগুলির জন্য রেজিস্ট্রেশন করবেন তখন এটি কার্যকর হবে না এবং আপনি পাবেন:

java.lang.SecurityException: প্রদত্ত কলার প্যাকেজ অ্যান্ড্রয়েড প্রক্রিয়া প্রক্রিয়াতে চলছে না Process


7

Kotlin

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

4

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

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

3
এটি কেবলমাত্র যদি আপনি একটি অভ্যন্তরীণ শ্রেণীর ভিতরে থাকেন তবে এটি কার্যকর হয়, যা ওপি-তে খুব কমই হয়।
রিচার্ড জে। রস তৃতীয়

3
এটি যতক্ষণ কাজ করবে ANA_METHOD কে মাইনএ্যাকটিভিটি তৈরির পরে বলা হয়ে থাকে তবে ক্রিয়াকলাপের স্থিতিশীল রেফারেন্সগুলি প্রায় অনিবার্যভাবে মেমরি ফাঁসের (ইতিমধ্যে উল্টাপাল্টির প্রশ্নের অন্যান্য প্রতিক্রিয়া হিসাবে উল্লেখ করা হয়) পরিচয় করিয়ে দেয়, সুতরাং আপনার যদি সত্যই স্থিতিশীল রেফারেন্স রাখতে হয় তবে অ্যাপ্লিকেশনটি ব্যবহার করুন শুধুমাত্র প্রসঙ্গ।
হ্যান্ডটওয়ার্ক

1
অন্তর্গত ক্লাসগুলি মন্দ সবচেয়ে খারাপ দিকটি হ'ল প্রচুর লোকেরা এসিঙ্কটাস্ক এবং এ জাতীয় জিনিসের জন্য এটি করে, কারণ অনেক টিউটোরিয়াল সেভাবে এটি করে ...
রেইনহার্ড

4

আপনি যদি ম্যানিফেস্ট ফাইলটি সংশোধন করতে না চান, আপনি নিজের প্রারম্ভিক ক্রিয়াকলাপটিতে ম্যানুয়ালি স্ট্যাটিক ভ্যারিয়েবলে প্রসঙ্গটি সংরক্ষণ করতে পারেন:

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
}

দ্রষ্টব্য: অন্যান্য সমস্ত উত্তরের মতো এটিও একটি সম্ভাব্য মেমরি ফাঁস।


1
এই ক্ষেত্রে প্রসঙ্গটি প্রয়োগের সাথে আবদ্ধ হওয়ায় এটি ঠিক কী ফুটো হবে? যদি অ্যাপ্লিকেশনটি মারা যায় তবে অন্য সব কিছু করে।
TheRealChx101

3

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

public static Context getAppContext()
   return MyApplication.context; 

3

এই উত্স অনুসারে আপনি 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();
    }
}

কন্টেক্সট্র্যাপারের জন্য জাভাডোক

প্রসংগের প্রক্সিং বাস্তবায়ন যা এর সমস্ত কলকে কেবল অন্য প্রসঙ্গে প্রেরণ করে। মূল প্রসঙ্গে পরিবর্তন না করে আচরণটি সংশোধন করতে সাবক্ল্যাস করা যেতে পারে।


1
এটা মজার. ContextWrapper সম্পর্কে শিখতে ভাল। তবে, যদি আপনাকে এই নির্মাতার কাছে অ্যাপ্লিকেশন প্রসঙ্গে পাস করার প্রয়োজন হয় তবে আপনার এখনও এটি অন্য কোথাও থেকে নেওয়া দরকার।
jk7

2

আপনি যদি কোনও কারণে অ্যাপ্লিকেশন প্রসঙ্গটি কোনও শ্রেণিতে চান তবে কেবল তাদের প্রয়োগ / ক্রিয়াকলাপ নয়, সম্ভবত কিছু কারখানা বা সহায়ক শ্রেণীর জন্য। আপনি আপনার অ্যাপটিতে নিম্নলিখিত সিঙ্গলটন যুক্ত করতে পারেন can

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

তারপরে এটি আপনার অ্যাপ্লিকেশন ক্লাসের অনক্রিয়েট দিয়ে শুরু করুন

GlobalAppContextSingleton.getInstance().initialize(this);

কল করে এটি যে কোনও জায়গায় ব্যবহার করুন

GlobalAppContextSingleton.getInstance().getApplicationContext()

আমি প্রয়োগের প্রসঙ্গ ব্যতীত অন্য কোনও ক্ষেত্রে এই পদ্ধতির প্রস্তাব দিই না। এটি স্মৃতি ফাঁস হতে পারে।


এটি শ্রেণীর / পদ্ধতির নামগুলি পাথরে সেট করা পছন্দ করে না, এটি দীর্ঘ রাখে এবং (আশা করি) একটি প্রশ্নোত্তরের জন্য বর্ণনামূলক, এটি আমার নিজের ব্যবহারের জন্য সংক্ষিপ্ত করে রেখেছিল।
ভার্সা

1

এটির জন্য আমাকে সহায়তা করতে আমি সিঙ্গলটন ডিজাইন প্যাটার্নের একটি প্রকরণ ব্যবহার করি।

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


আপনার যা যা প্রয়োজন তা যদি প্রসঙ্গে হয় তবে আপনি ক্রিয়াকলাপটি বলতে পারেন get অ্যাপ্লিকেশন কনটেক্সট (); এটি ফাঁসের বিষয়ে চিন্তা না করে স্থিতিশীলভাবে ধরে রাখা যেতে পারে।
মিনিসম্যান

2
এটি মেমরি ফাঁস তৈরি করবে
ব্লু উইজার্ড

1

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

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

$.act()

একজন WeakReference , গার্বেজ কালেকশন মূল বস্তু reclaiming প্রতিরোধ ছাড়া একটি রেফারেন্স বজায় রাখে যাতে আপনি মেমরি তথ্য ফাঁসের সঙ্গে একটি সমস্যা থাকবে না।

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

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

$.act(Activity);

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

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


1
স্পষ্টতই এটিকে নিচু করা হয়েছে .. একটি ব্যাখ্যা ভাল হবে !?
দারিয়াস

1
আমি এটিকে হ্রাস করি নি, তবে জাভাস্ক্রিপ্টের হাতে থাকা প্রশ্নটির সাথে কোনও সম্পর্ক নেই, যা আপনার যে কোনও ডাউনওয়েটকে ব্যাখ্যা করবে! চিয়ার্স।
এরনানি জোপার্প্ট

এটি একটি সাবলীল ইন্টারফেসের মতো jQuery এর কিছু দিক এবং তার বিমূর্ততা দ্বারা অনুপ্রাণিত হয়ে এটিকে প্রশংসনীয় অযৌক্তিক হতে হবে .. এগুলি অন্তর্নিহিত ভাষার নীতিগুলি অজ্ঞেয়!
দারিয়াস

1
সুতরাং আপনি এটিকে নিম্নগঠিত করছেন কারণ এটি একই কাঠামোর নয় এমন ফ্রেমওয়ার্কের এপিআই শব্দার্থ দ্বারা অনুপ্রাণিত হয়েছিল ?! আমার মনে হয় আপনি ছেলেরা প্ল্যাটফর্ম-অজ্ঞাত নীতি প্রয়োগের বিষয়টিটি মিস করেছেন .....................................
দারিয়াস

3
এই উত্তরটি পুরোপুরি জাভাস্ক্রিপ্টের সাথে সম্পর্কিত নয়। উত্তরটি
ডাউনওয়োট

1

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


1
তুমি ঠিক. এবং এটি স্মৃতি ফাঁস হতে হবে!
ব্যবহারকারী1506104

1

কোটলিনে, সঙ্গী অবজেক্টে প্রসঙ্গ / অ্যাপ কনটেক্সট লাগানো সতর্কতা উত্পন্ন করে 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
}

অথবা আপনি এটিকে আরও নিরাপদে ব্যবহারযোগ্য ননযোগ্য প্রকারটি ব্যবহার করতে পারেন:

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

আশা করি এটি সাহায্য করবে।


এই কোরহেল্পারের অবজেক্ট ক্লাসটি আরম্ভ করা হবে এবং পরবর্তী পর্যায়ে ক্রিয়াকলাপের মাধ্যমে ব্যবহার করা যাবে? দুঃখিত আমি কোটলিনে নতুন
ডাঃ এএনড্রো

হ্যাঁ অবশ্যই.
হায়ি নুকমান

-1

এরকম কিছু চেষ্টা করুন

import androidx.appcompat.app.AppCompatActivity;  
import android.content.Context; 
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    private static Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = getApplicationContext();
    }

    public static void getContext(View view){
        Toast.makeText(context, "Got my context!",
                    Toast.LENGTH_LONG).show();    
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.