অ্যাপ্লিকেশন প্রসঙ্গটি সর্বত্র ব্যবহার করছেন?


476

একটি অ্যান্ড্রয়েড অ্যাপে নিম্নলিখিত পদ্ধতির সাথে কিছু ভুল আছে:

public class MyApp extends android.app.Application {

    private static MyApp instance;

    public MyApp() {
        instance = this;
    }

    public static Context getContext() {
        return instance;
    }

}

এবং যেখানেই প্রাসঙ্গিক প্রয়োজন (এবং অবশ্যই ফাঁস নয়) যেখানে এটিকে সর্বত্র পাস করুন (উদাহরণস্বরূপ SQLiteOpenHelper)?


23
শুধু এই বাস্তবায়নের অন্যদের জন্য সম্প্রসারিত করার পরে, সংশোধন করতে পারেন <application>আপনার AndroidManifest.xml ফাইলের নোড নিম্নলিখিত বৈশিষ্ট্য সংজ্ঞা অন্তর্ভুক্ত করা: android:name="MyApp"। মাই অ্যাপটি একই প্যাকেজের অধীনে থাকা দরকার যা আপনার ম্যানিফেস্ট উল্লেখ করে।
ম্যাট হাগিনস

6
এসকিউএলওপেনহেল্পারে একটি প্রসঙ্গ সরবরাহ করার সমস্যাটি ঘুরে দেখার দুর্দান্ত উপায় !! আমি একটি সিঙ্গেলটন "এসকিউএলটি ম্যানেজার" প্রয়োগ করেছি এবং আটকে গিয়েছিলাম "এফ কীভাবে আমি সিঙ্গলটনে একটি প্রসঙ্গ পেতে পারি?"
কেউ কোথাও কোথাও

8
ঠিক তাই আপনি জানেন যে আপনি তার অ্যাপ্লিকেশনটিকে তার একটি সুপার ইন্টারফেসের মাধ্যমে ফিরিয়ে দিচ্ছেন, তাই আপনি মাই অ্যাপের মধ্যে যদি অতিরিক্ত পদ্ধতি সরবরাহ করেন তবে আপনি সেগুলি ব্যবহার করতে পারবেন না। আপনার getContext () এর পরিবর্তে আমার অ্যাপ্লিকেশনটির একটি রিটার্ন টাইপ থাকা উচিত, এবং সেইভাবে আপনি পরে যুক্ত পদ্ধতিগুলি, পাশাপাশি ContextWrapper এবং Context এর সমস্ত পদ্ধতি ব্যবহার করতে পারেন।

5
Goo.gl/uKcFn দেখুন - এটি একই পোস্টের সাথে সম্পর্কিত আরও একটি জবাব। অনক্রিটে স্থিতিশীল ভেরিয়েবল সেট করুন এবং কেটার নয় Bet
অ্যালিকেলজিন-কিলাকা

1
@ চুংফ্যাম যদি ফ্রেমওয়ার্কটি আপনার অ্যাপ্লিকেশনটিকে মেরে ফেলেছে তবে শূন্য প্রসঙ্গে অ্যাক্সেস করার কিছুই থাকবে না ...
কেভিন ক্রামউইডে

উত্তর:


413

এই পদ্ধতির সাথে বেশ কয়েকটি সম্ভাব্য সমস্যা রয়েছে, যদিও অনেক পরিস্থিতিতে (যেমন আপনার উদাহরণ হিসাবে) এটি ভালভাবে কাজ করবে।

বিশেষ করে আপনি সতর্কতা অবলম্বন কিছু সঙ্গে পুলিশ সঙ্গে তার আচরণ হওয়া উচিত GUIযে একটি প্রয়োজন Context। উদাহরণস্বরূপ, আপনি যদি কনটেক্সট অ্যাপ্লিকেশনটি পাস করেন তবে আপনি LayoutInflaterএকটি ব্যতিক্রম পাবেন। সাধারণভাবে বলতে গেলে, আপনার পদক্ষেপ চমৎকার: এটি একটি ব্যবহার করতে ভাল অভ্যাস Activity's Contextমধ্যে যে Activity, এবং Application Contextযখন একটি পরিধি বহির্ভূত একটি প্রসঙ্গ ক্ষণস্থায়ী Activityথেকে মেমরি তথ্য ফাঁসের এড়াতে

এছাড়াও, আপনার প্যাটার্নের বিকল্প হিসাবে আপনি অ্যাপ্লিকেশন প্রসঙ্গটি পেতে getApplicationContext()কোনও Contextবস্তুর (যেমন একটি ক্রিয়াকলাপ) এ কল করার শর্টকাট ব্যবহার করতে পারেন ।


22
একটি অনুপ্রেরণামূলক উত্তরের জন্য ধন্যবাদ। আমি মনে করি আমি এই পদ্ধতিটি কেবলমাত্র দৃ .়তার স্তরের জন্য ব্যবহার করব (যেমন আমি সামগ্রী সরবরাহকারীদের সাথে যেতে চাই না)। ভেবে অবাক হচ্ছেন যে এসকিউএলওপেনহেল্পারকে এমনভাবে ডিজাইন করার পিছনে কী অনুপ্রেরণা ছিল যা অ্যাপ্লিকেশন থেকে তা অর্জনের পরিবর্তে কোনও প্রসঙ্গ সরবরাহ করা হবে বলে আশা করে। পিএস এবং আপনার বই দুর্দান্ত!
yanchenko

7
LayoutInflatorস্রেফ আমার জন্য কাজ করে অ্যাপ্লিকেশন প্রসঙ্গ ব্যবহার করে । গত তিন বছরে অবশ্যই পরিবর্তন করা হয়েছে।
জ্যাকব ফিলিপস

5
ক্রিয়াকলাপের প্রসঙ্গ ছাড়াই @ জ্যাকবফিলিপগুলি লেআউটআইনফ্লেটার ব্যবহার করে সেই ক্রিয়াকলাপের স্টাইলিংটি মিস হবে। সুতরাং এটি এক অর্থে কাজ করবে, তবে অন্য নয়।
চিহ্নিত করুন

1
@ মারককার্টার আপনি কি অ্যাপ্লিকেশন প্রসঙ্গটি ব্যবহার করে ক্রিয়াকলাপের স্টাইলিংটি মিস করবেন?
জ্যাকব ফিলিপস

1
@ জ্যাকবফিলিপস হ্যাঁ, অ্যাপ্লিকেশন প্রসঙ্গে স্টাইলিং থাকতে পারে না কারণ প্রতিটি ক্রিয়াকলাপ আলাদাভাবে স্টাইল করা হতে পারে।
চিহ্নিত করুন

28

আমার অভিজ্ঞতায় এই পদ্ধতির প্রয়োজন হবে না। আপনার যদি কোনও কিছুর জন্য প্রসঙ্গের প্রয়োজন হয় তবে আপনি সাধারণত দেখুন.জেটকন্টেক্সট () এ কল করার মাধ্যমে এবং এটি Contextপ্রাপ্ত ব্যবহার করে কনটেক্সট.জেট অ্যাপ্লিকেশনস কনটেক্সট () কল করতে পারেন Applicationপ্রসঙ্গটি পেতে । আপনি যদি Applicationপ্রসঙ্গটি এটির থেকে পেতে চেষ্টা করেন তবে আপনি Activityসর্বদা Activity.get অ্যাপ্লিকেশন () এ কল করতে পারেন যা Contextকল করার জন্য প্রয়োজনীয় হিসাবে পাস হতে সক্ষম হওয়া উচিত SQLiteOpenHelper()

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


13

কিছু লোক জিজ্ঞাসা করেছেন: সিঙ্গলটন কীভাবে নাল পয়েন্টার ফিরিয়ে দিতে পারে? আমি এই প্রশ্নের উত্তর দিচ্ছি। (আমি কোনও মন্তব্যে উত্তর দিতে পারি না কারণ আমার কোড পোস্ট করা দরকার))

এটি দুটি ইভেন্টের মধ্যে শূন্য হতে পারে: (1) শ্রেণিটি লোড হয় এবং (2) এই শ্রেণীর অবজেক্ট তৈরি হয় is এখানে একটি উদাহরণ:

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.xinstance এবং X.yinstance হয় নাল ; তারা নাল কারণ ভেরিয়েবল X.xinstance উত্তর Y.yinstance পাঠ করা হয় যখন তারা নাল ছিল।

এটি কি স্থির করা যায়? হ্যাঁ,

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

তবে এটি অ্যান্ড্রয়েড Applicationঅবজেক্টের জন্য কোনও বিকল্প নয় : প্রোগ্রামার তৈরি হওয়ার সময় নিয়ন্ত্রণ করে না।

আবার: প্রথম উদাহরণ এবং দ্বিতীয়টির মধ্যে পার্থক্য হ'ল স্থির পয়েন্টারটি শূন্য হলে দ্বিতীয় উদাহরণটি উদাহরণ তৈরি করে। কিন্তু একটি প্রোগ্রামার তৈরি করতে পারবেন না Android অ্যাপ্লিকেশান বস্তুর সামনে সিস্টেম এটা করতে সিদ্ধান্ত নেয়।

হালনাগাদ

আর একটি চমকপ্রদ উদাহরণ যেখানে প্রারম্ভিক স্ট্যাটিক ক্ষেত্রগুলি ঘটে null

মাইন.জভা :

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

নোট করুন যে আপনি স্থিতিশীল ভেরিয়েবল ডিক্লেয়ারেশনটিকে এক লাইন উপরের দিকে সরাতে পারবেন না, কোডটি সংকলন করবে না।


3
দরকারী উদাহরণ; এটি যেমন একটি গর্ত আছে তা জেনে রাখা ভাল। আমি এর থেকে যা সরিয়ে নিচ্ছি তা হ'ল যে কোনও শ্রেণীর স্ট্যাটিক ইনিশিয়ালাইজের সময় এমন স্ট্যাটিক ভেরিয়েবলের উল্লেখ করা এড়ানো উচিত।
টুলমেকারস্টেভ

10

আবেদনের শ্রেণি:

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

}

অ্যান্ড্রয়েড ম্যানিফেস্টে অ্যাপ্লিকেশনটি ঘোষণা করুন:

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

ব্যবহার:

MyApplication.getAppContext()

1
স্মৃতি ফাঁস হওয়ার প্রবণতা রয়েছে। আপনার কখনই এটি করা উচিত নয়।
ড্রাগস

9

আপনি অ্যাপ্লিকেশন প্রসঙ্গটি পেতে একটি মোড়ক তৈরি করার চেষ্টা করছেন এবং এটি nullপয়েন্টারটি ফিরে আসার সম্ভাবনা রয়েছে ।

আমার বোঝাপড়া অনুসারে, আমি কল করতে তার আরও ভাল পদ্ধতির অনুমান করি - 2 Context.getApplicationContext() বা যে কোনও একটি Activity.getApplication()


13
কখন তা শূন্য হবে?
আটকে

25
এমন কোনও স্থিতিশীল প্রসঙ্গ নেই। আমি কিছু অনুপস্থিত করছি?
ডালচন্তরা

আমি আমার অ্যাপ্লিকেশনেও একই পদ্ধতির প্রয়োগ করি, তবে এসকিউএলইটহেনহেল্পারে কল করার সময় এটি নাল পয়েন্টারটি দেয়। এই ধরনের পরিস্থিতির জন্য কোনও উত্তর।
অশুতোষ

2
আপনি যদি অ্যাপ্লিকেশনের আগে লোড হওয়া কোনও কনটেন্টপ্রাইডারে এসকিউএলইটওপেনহেলপারকে কল করেন তবে এটি হতে পারে।
গুনার বার্নস্টেইন

5

এটি একটি ভাল পদ্ধতির। আমি নিজেও এটি ব্যবহার করি। আমি কেবল onCreateকনস্ট্রাক্টর ব্যবহার না করে সিঙ্গলটন সেট করতে ওভাররাইড করার পরামর্শ দেব ।

এবং যেহেতু আপনি উল্লেখ করেছেন SQLiteOpenHelper: onCreate ()আপনি ডাটাবেসটিও খুলতে পারেন।

ব্যক্তিগতভাবে আমি মনে করি ডকুমেন্টেশনটি ভুলভাবে বলেছে যে সাধারণত সাবক্লাস অ্যাপ্লিকেশন করার দরকার নেই । আমি মনে করি বিপরীতটি সত্য: আপনার সর্বদা সাবক্লাস অ্যাপ্লিকেশন হওয়া উচিত।


3

আমি কনস্ট্রাক্টরে একটি সিস্টেম পরিষেবা পেতে অ্যাপ্লিকেশন কনটেক্সট ব্যবহার করব। এটি পরীক্ষার সহজতর করে এবং সংমিশ্রণ থেকে উপকার করে

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

}

টেস্ট ক্লাস তখন ওভারলোডেড কনস্ট্রাক্টর ব্যবহার করবে।

অ্যান্ড্রয়েড ডিফল্ট কনস্ট্রাক্টর ব্যবহার করবে।


1

আমি এটি পছন্দ করি তবে এর পরিবর্তে আমি একটি সিঙ্গলটন প্রস্তাব করব:

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

31
Android.app.application প্রসারিত করা ইতিমধ্যে সিঙ্গলটনের গ্যারান্টি দেয় তাই এটি অপ্রয়োজনীয়
ভিনসেন্ট

8
আপনি যদি অ-অ্যাক্টিভিটি ক্লাস থেকে অ্যাক্সেস চান?
ম্যাক্সরুনার

9
আপনার newনিজের কখনই অ্যাপ্লিকেশনটি করা উচিত নয় (ইউনিট পরীক্ষার সম্ভাব্য ব্যতিক্রম সহ)। অপারেটিং সিস্টেম এটি করবে। আপনার কোনও কনস্ট্রাক্টরও থাকা উচিত নয়। এটা কি onCreateজন্য হয়।
মার্টিন

@ ভিনসেন্ট: আপনি কি কিছু লিঙ্ক পোস্ট করতে পারেন? বাঞ্ছনীয় কোড - আমি এখানে জিজ্ঞাসা করছি: stackoverflow.com/questions/19365797/...
Mr_and_Mrs_D

@ আরজজিও কেন আমরা কনস্ট্রাক্টরে এটি করা উচিত নয়?
মিহা_এক্স 64

1

আমি একই পদ্ধতির ব্যবহার করছি, আমি সিঙ্গলটনকে আরও ভালভাবে লেখার পরামর্শ দিচ্ছি:

public static MyApp getInstance() {

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

    return instance;
}

তবে আমি সর্বত্র ব্যবহার করছি না, আমি ব্যবহার করি getContext()এবং getApplicationContext()আমি এটি কোথায় করতে পারি!


সুতরাং, কেন আপনি উত্তরটি কম করে রেখেছেন তা বুঝতে দয়া করে একটি মন্তব্য লিখুন যাতে আমি বুঝতে পারি। সিঙ্গলটন পদ্ধতির বহিঃপ্রকাশ বা বাহ্যিক দৃশ্যের বাইরে কোনও বৈধ প্রসঙ্গ পেতে ব্যাপকভাবে ব্যবহৃত হয় ...
সেরফিমের

1
অপারেটিং সিস্টেমটি নিশ্চিত করে যে অ্যাপ্লিকেশনটি ঠিক একবার ইনস্ট্যান্ট করা আছে No যদি কোনও হয় তবে আমি সিঞ্জেলটনকে অনক্রিট () এ সেট করার পরামর্শ দিচ্ছি।
মার্টিন

1
অলসভাবে অবিরাম করার একটি ভাল থ্রেড-নিরাপদ উপায়, তবে এখানে প্রয়োজনীয় নয়।
নেক্সা

2
বাহ, ঠিক যখন আমি ভেবেছিলাম মানুষ পরিশেষে ডাবল চেক করা লকিং ব্যবহার বন্ধ ছিল ... cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
সোরেন Boisen
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.