অ্যান্ড্রয়েডে গ্লোবাল ভেরিয়েবল কীভাবে ঘোষণা করবেন?


595

আমি একটি অ্যাপ্লিকেশন তৈরি করছি যার জন্য লগইন প্রয়োজন। আমি মূল এবং লগইন ক্রিয়াকলাপ তৈরি করেছি।

মূল ক্রিয়াকলাপ onCreateপদ্ধতিতে আমি নিম্নলিখিত শর্তটি যুক্ত করেছি:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ...

    loadSettings();
    if(strSessionString == null)
    {
        login();
    }
    ...
}

onActivityResultপদ্ধতি যা মৃত্যুদন্ড কার্যকর হয় যখন লগইন ফর্ম ভালো দেখায় বন্ধ:

@Override
public void onActivityResult(int requestCode,
                             int resultCode,
                             Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    switch(requestCode)
    {
        case(SHOW_SUBACTICITY_LOGIN):
        {
            if(resultCode == Activity.RESULT_OK)
            {

                strSessionString = data.getStringExtra(Login.SESSIONSTRING);
                connectionAvailable = true;
                strUsername = data.getStringExtra(Login.USERNAME);
            }
        }
    }

সমস্যাটি হ'ল লগইন ফর্মটি কখনও কখনও দু'বার প্রদর্শিত হয় ( login()পদ্ধতিটি দু'বার বলা হয়) এবং ফোনের কীবোর্ড স্লাইড করলে লগইন ফর্মটি আবার উপস্থিত হয় এবং আমি অনুমান করি সমস্যাটি পরিবর্তনশীল strSessionString

ব্যবহারকারী ইতিমধ্যে সফলভাবে প্রমাণীকরণের পরে লগইন ফর্ম প্রদর্শিত না হওয়ার জন্য কী কী পরিবর্তনশীল বৈশ্বিক সেট করবেন তা জানেন?


সেভ ইনস্ট্যান্স স্টেট বান্ডেল quicktips.in/…
দীপক স্বামী

উত্তর:


954

আমি এই উত্তরটি '09-এ ফিরে লিখেছিলাম যখন অ্যান্ড্রয়েড তুলনামূলকভাবে নতুন ছিল, এবং অ্যান্ড্রয়েড বিকাশে অনেকগুলি প্রতিষ্ঠিত নয়। আমি এই পোস্টের নীচে একটি দীর্ঘ সংযোজন যুক্ত করেছি, কিছু সমালোচনা সম্বোধন করে, এবং সাবক্লাসিং অ্যাপ্লিকেশন না করে সিঙ্গেলটনের ব্যবহারের সাথে আমার যে দার্শনিক মতবিরোধ রয়েছে তা বিশদ বর্ণনা করছি। এটি আপনার নিজের ঝুঁকিতে পড়ুন।

মূল উত্তর:

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

যেমন আপনি জানেন, প্রতিটি ক্রিয়াকলাপ একটি প্রসঙ্গও, যা বিস্তৃত অর্থে এর কার্যকরকরণ পরিবেশ সম্পর্কে তথ্য। আপনার অ্যাপ্লিকেশনটির একটি প্রসঙ্গও রয়েছে এবং অ্যান্ড্রয়েড গ্যারান্টি দেয় যে এটি আপনার অ্যাপ্লিকেশন জুড়ে একক উদাহরণ হিসাবে উপস্থিত থাকবে।

এটি করার উপায় হ'ল android.app . প্রয়োগের নিজস্ব সাবক্লাস তৈরি করা এবং তারপরে আপনার ম্যানিফেস্টে অ্যাপ্লিকেশন ট্যাগে সেই শ্রেণিটি নির্দিষ্ট করা। এখন অ্যান্ড্রয়েড স্বয়ংক্রিয়ভাবে সেই শ্রেণীর একটি উদাহরণ তৈরি করবে এবং আপনার সম্পূর্ণ অ্যাপ্লিকেশনের জন্য এটি উপলব্ধ করবে। আপনি এটি যে কোনও থেকে অ্যাক্সেস করতে পারেনcontextContext.getApplicationContext() পদ্ধতি ব্যবহার করে ( Activityএমন পদ্ধতিও দেয় getApplication()যা ঠিক একই প্রভাব ফেলে)। নিম্নলিখিতটি একটি চূড়ান্ত সরলীকৃত উদাহরণ, অনুসরণ করার জন্য সতর্কতা সহ:

class MyApp extends Application {

  private String myState;

  public String getState(){
    return myState;
  }
  public void setState(String s){
    myState = s;
  }
}

class Blah extends Activity {

  @Override
  public void onCreate(Bundle b){
    ...
    MyApp appState = ((MyApp)getApplicationContext());
    String state = appState.getState();
    ...
  }
}

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

উপরের উদাহরণ থেকে কিছু লক্ষণীয়; ধরুন আমরা এর পরিবর্তে কিছু করেছিলাম:

class MyApp extends Application {

  private String myState = /* complicated and slow initialization */;

  public String getState(){
    return myState;
  }
}

এখন এই ধীর সূচনা (যেমন হিট ডিস্ক, হিটিং নেটওয়ার্ক, কোনও কিছু ব্লক করা ইত্যাদি) প্রতিবার অ্যাপ্লিকেশন তাত্ক্ষণিকভাবে সঞ্চালিত হবে! আপনি ভাবতে পারেন, ভাল, প্রক্রিয়াটির জন্য এটি কেবল একবার এবং আমাকে যাইহোক খরচ দিতে হবে, তাই না? উদাহরণস্বরূপ, ডায়ান হ্যাকোর্ন নীচে যেমন উল্লেখ করেছেন, আপনার প্রক্রিয়াটি তাত্ক্ষণিকভাবে করা সম্ভব - ঠিক করা- একটি ব্যাকগ্রাউন্ড সম্প্রচার ইভেন্ট পরিচালনা করতে। যদি আপনার সম্প্রচার প্রক্রিয়াজাতকরণটির এই রাজ্যের কোনও প্রয়োজন না থাকে তবে আপনি সম্ভাব্যভাবে কিছুই এবং অবিচ্ছিন্ন ক্রিয়াকলাপের পুরো সিরিজটি সম্পন্ন করেছেন। অলস তাত্পর্য এখানে গেমের নাম। নিম্নলিখিতটি অ্যাপ্লিকেশন ব্যবহারের কিছুটা জটিল পদ্ধতি যা ব্যবহারের সহজতম ব্যতীত অন্য কোনও কিছুর জন্য আরও বেশি অর্থবোধ করে:

class MyApp extends Application {

  private MyStateManager myStateManager = new MyStateManager();

  public MyStateManager getStateManager(){
    return myStateManager ;
  }
}

class MyStateManager {

  MyStateManager() {
    /* this should be fast */
  }

  String getState() {
    /* if necessary, perform blocking calls here */
    /* make sure to deal with any multithreading/synchronicity issues */

    ...

    return state;
  }
}

class Blah extends Activity {

  @Override
  public void onCreate(Bundle b){
    ...
    MyStateManager stateManager = ((MyApp)getApplicationContext()).getStateManager();
    String state = stateManager.getState();
    ...
  }
}

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

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

<application
     android:name="my.application.MyApp" 
     android:icon="..."
     android:label="...">
</application>

দ্রষ্টব্য 2: ব্যবহারকারী 608578 নীচে জিজ্ঞাসা করছে যে এটি কীভাবে নেটিভ অবজেক্ট লাইফসাইকেলগুলি পরিচালনা করে? আমি অল্প অল্প সময়েই অ্যান্ড্রয়েডের সাথে নেটিভ কোড ব্যবহারের গতি বাড়িয়ে তুলছি না এবং এটি কীভাবে আমার সমাধানের সাথে ইন্টারেক্ট করবে তা জবাব দেওয়ার জন্য আমি যোগ্য নই। কারও কাছে যদি এর উত্তর থাকে তবে আমি তাদের creditণ দিতে এবং সর্বাধিক দৃশ্যমানতার জন্য তথ্যটি এই পোস্টে রাখতে প্রস্তুত।

সংযোজন:

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

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

ডায়ান বলেছেন, "অ্যাপ্লিকেশন থেকে সাবক্লাস করার কোনও কারণ নেই। এটি একটি সিঙ্গলটন তৈরির চেয়ে আলাদা নয় ..." এই প্রথম দাবিটি ভুল। এই জন্য দুটি প্রধান কারণ আছে। 1) অ্যাপ্লিকেশন বর্গটি কোনও অ্যাপ্লিকেশন বিকাশকারীর জন্য আরও ভাল আজীবন গ্যারান্টি সরবরাহ করে; এটির আবেদনের আজীবন গ্যারান্টি রয়েছে। একটি সিঙ্গলটন আবেদনের আজীবনের সাথে একচেটিয়াভাবে আবদ্ধ নয় (যদিও এটি কার্যকরভাবে রয়েছে)। এটি আপনার গড় অ্যাপ্লিকেশন বিকাশকারীদের জন্য একটি অ-ইস্যু হতে পারে তবে আমি যুক্তিটি বলতে চাই এটি ঠিক একই ধরণের অ্যান্ড্রয়েড এপিআইয়ের প্রস্তাব করা উচিত, এবং এটি এর সাথে সম্পর্কিত জীবনকাল হ্রাস করে অ্যান্ড্রয়েড সিস্টেমে আরও অনেক নমনীয়তা সরবরাহ করে ডেটা। ২) অ্যাপ্লিকেশন বর্গটি অ্যাপ্লিকেশন বিকাশকারীকে একক দৃষ্টান্ত ধারক সহ রাষ্ট্রের জন্য সরবরাহ করে, যা একক রাষ্ট্রের একক ধারক থেকে পৃথক। পার্থক্যের তালিকার জন্য উপরের সিঙ্গলটন ব্যাখ্যার লিঙ্কটি দেখুন।

ডায়ান এগিয়ে চলেছে, "... ভবিষ্যতে আপনার অনুশোচিত কিছু হওয়ার কারণ সম্ভবত আপনি যখন নিজের অ্যাপ্লিকেশন অবজেক্টটি স্বতন্ত্র অ্যাপ্লিকেশন যুক্তিযুক্ত হওয়া উচিত তখন এটির এই বিভ্রান্তিকর জঞ্জাল হয়ে উঠছে" " এটি অবশ্যই ভুল নয়, তবে এটি অ্যাপ্লিকেশন সাবক্লাসের উপরে সিঙ্গেলটন বেছে নেওয়ার কোনও কারণ নয়। ডায়ানের কোনও যুক্তিই যুক্তি সরবরাহ করে না যে একটি অ্যাপ্লিকেশন সাবক্লাসের চেয়ে সিঙ্গেলটন ব্যবহার করা ভাল, তিনি যে প্রতিষ্ঠানের চেষ্টা করেন তা হ'ল সিঙ্গলটন ব্যবহার করা কোনও অ্যাপ্লিকেশন সাবক্লাসের চেয়ে খারাপ নয়, যা আমি বিশ্বাস করি যে এটি মিথ্যা।

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

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

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

পূর্ববর্তী স্ট্যাক এক্সচেঞ্জ লিঙ্ক থেকে চুরি হওয়া হিসাবে আমি আপনাকে সিঙ্গলটনে ডাউনসাইডগুলির নীচের তালিকাটি রেখে চলেছি:

  • বিমূর্ত বা ইন্টারফেস ক্লাস ব্যবহারে অক্ষমতা;
  • সাবক্লাসে অক্ষমতা;
  • অ্যাপ্লিকেশন জুড়ে উচ্চ সংযুক্তকরণ (সংশোধন করা কঠিন);
  • পরীক্ষা করা কঠিন (ইউনিট পরীক্ষায় জাল / উপহাস করতে পারবেন না);
  • পরিবর্তনীয় অবস্থার ক্ষেত্রে সমান্তরাল হওয়া কঠিন (ব্যাপক লকিং প্রয়োজন);

এবং আমার নিজের যুক্ত করুন:

  • অস্পষ্ট এবং অযৌক্তিক জীবনকালীন চুক্তি অ্যান্ড্রয়েড (বা অন্যান্য বেশিরভাগ) বিকাশের জন্য অসমর্থিত;

93
আপনাকে শীঘ্রই ধন্যবাদ - এই ধরণের উত্তরগুলি হ'ল আমি স্ট্যাক ওভারফ্লোকে এত পছন্দ করি। দারূন কাজ!
জনিলম্বদা

5
"আপনার ম্যানিফেস্টে অ্যাপ্লিকেশন ট্যাগে সেই শ্রেণিটি কীভাবে নির্দিষ্ট করবেন" এর জন্য যে কেউ ভাবছেন, এই লেখার মতো এই প্রশ্নটির জন্য আরও দুটি উত্তর রয়েছে যা এটি কীভাবে করবেন তা বর্ণনা করে (অ্যান্ড্রয়েড: নাম ব্যবহার করুন), একজন ইবুপ্রোফেন এবং একটি মাইক ব্রাউন দ্বারা।
টাইলার কলিয়ার

9
শীঘ্রই, আপনার উত্তরটি সঠিক, তবে আপনি কি লক্ষ্য করতে পারেন যে আমাদের <অ্যাপ্লিকেশন অ্যান্ড্রয়েড: নাম = "My মাই অ্যাপ" ... /> অ্যান্ড্রয়েড ম্যানিফেস্ট ফাইলটিতে যুক্ত করা উচিত?
anticafe

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

14
এছাড়াও, আসুন এখানে প্রকৃতপক্ষে পরিষ্কার হওয়া যাক - সিঙ্গেলনের বিরুদ্ধে আপনার সমস্ত যুক্তি পুরোপুরি বৈধ, যখন আমরা এমন পরিস্থিতি সম্পর্কে কথা বলি যেখানে আপনি বাস্তবে একটি সিঙ্গলটন এবং অন্য পদ্ধতির মধ্যে বেছে নিচ্ছেন যা বৈশ্বিক নয়; সিলেটলেটগুলি গ্লোবাল হয়, সমস্ত গ্লোবালগুলি প্রয়োগ হয় যা প্রয়োগ হয়। তবে অ্যাপ্লিকেশনটিও একটি সিঙ্গলটন । সাবক্লাসিং অ্যাপ্লিকেশনটিতে স্যুইচ করে আপনি এই সমস্যাগুলি থেকে মুক্তি পাচ্ছেন না, একটি অ্যাপ্লিকেশন হ'ল সিঙ্গলটনের মতোই (তবে আরও খারাপ), এটি আপনাকে নিজেকে আরও পরিষ্কার করার মতো করে দিচ্ছে যে আপনি আরও পরিষ্কার কিছু করছেন। কিন্তু আপনি না।
হ্যাকবড

153

এই সাবক্লাস তৈরি করুন

public class MyApp extends Application {
  String foo;
}

অ্যান্ড্রয়েড ম্যানিফেস্ট.এক্সএমএলে অ্যান্ড্রয়েড যুক্ত করুন: নাম

উদাহরণ

<application android:name=".MyApp" 
       android:icon="@drawable/icon" 
       android:label="@string/app_name">

1
তার জন্য ধন্যবাদ. আমি কীভাবে ম্যানিফেস্টে এটি ঘোষণার জন্য ভাবছিলাম
কেউ কোথাও

3
এটি আমার পক্ষে কাজ করার জন্য আমাকে "অপসারণ" করতে হয়েছিল। ".Myapp"
কেউ কোথাও

3
কেবলমাত্র মূল ক্রিয়াকলাপের পরে এটি ঘোষণা করুন , অন্যথায় এটি ইনস্টল / স্থাপন করতে না পারে
সামি

11
শুধু বলতে চাই, এটি মেইন অ্যাপ্লিকেশন ট্যাগটিতে যায় যা ইতিমধ্যে রয়েছে ... এটি দ্বিতীয়টি নয়: হার্ড উপায় শিখতে হয়েছিল।
বুয়ুগি

java.lang.IllegalAccessException: access to class is not allowed
র‌্যাটার

142

অ্যাপ্লিকেশনটির জন্য একটি রাষ্ট্র রাখার সুনিল পদ্ধতি দ্বারা প্রস্তাবিত পরামর্শটি ভাল, তবে এটির একটি দুর্বল বিষয় রয়েছে - এমন কিছু ক্ষেত্রে রয়েছে যখন ওএস সম্পূর্ণ অ্যাপ্লিকেশন প্রক্রিয়াটিকে হত্যা করে। প্রক্রিয়া এবং জীবনচক্রগুলি - এটি সম্পর্কিত ডকুমেন্টেশন এখানে ।

একটি কেস বিবেচনা করুন - আপনার অ্যাপ ব্যাকগ্রাউন্ডে চলে গেছে কারণ কেউ আপনাকে কল করছে (ফোন অ্যাপটি এখন পূর্বগ্রাউন্ডে রয়েছে)। এই ক্ষেত্রে && তে কিছু অন্যান্য শর্তে (ওপরের লিঙ্কটি তারা কী হতে পারে তার জন্য পরীক্ষা করুন) ওএস আপনার Applicationসাবস্ক্লাস উদাহরণ সহ আপনার অ্যাপ্লিকেশন প্রক্রিয়াটিকে হত্যা করতে পারে । ফলস্বরূপ রাজ্যটি হারিয়ে যায়। আপনি পরে যখন অ্যাপ্লিকেশনটিতে ফিরে আসবেন, তখন ওএস তার ক্রিয়াকলাপ স্ট্যাক এবং Applicationসাবক্লাস উদাহরণ পুনরুদ্ধার করবে , তবে myStateক্ষেত্রটি হবে null

আফাইক, রাষ্ট্রীয় সুরক্ষার গ্যারান্টি দেওয়ার একমাত্র উপায় হ'ল রাষ্ট্রকে টিকিয়ে রাখার যে কোনও ধরণের ব্যবহার, উদাহরণস্বরূপ অ্যাপ্লিকেশন ফাইলের জন্য ব্যক্তিগত ব্যবহার করা বা SharedPrefernces(এটি শেষ পর্যন্ত অভ্যন্তরীণ ফাইল সিস্টেমের মধ্যে অ্যাপ্লিকেশন ফাইলের জন্য একটি ব্যক্তিগত ব্যবহার করে)।


10
+1 সহ্য করার জন্য SharedPreferences; এইভাবে আমি এটি সম্পন্ন দেখেছি। আমি সংরক্ষিত রাষ্ট্রের জন্য পছন্দসই সিস্টেমটিকে অপব্যবহার করা অদ্ভুত বলে মনে করি তবে এটি এত ভালভাবে কাজ করে যে বিষয়টি কেবল পরিভাষার প্রশ্নে পরিণত হয়েছে।
চিজমিস্টার

1
আপনি দয়া করে কোডটি পোস্ট করতে পারেন (বা অর্ধিমিড বর্ণনা করেছেন যে সমস্যাটি সমাধান করার জন্য কীভাবে SharedPreferences ব্যবহার করা হয় সে সম্পর্কে
কেউ কেউ কোথাও

2
অগ্রাধিকার, ডাটাবেস, ফাইল সিরিয়ালাইজেশন ইত্যাদি প্রতিটি কার্যকলাপ যদি সেভআইন্সট্যান্সস্টেট ব্যবহার করে তবে রাষ্ট্রটি বজায় রাখতে পারে তবে ব্যবহারকারী যদি কার্যকলাপটি থেকে সরে যায় এবং যা ইতিহাসের স্ট্যাক থেকে সরিয়ে দেয়, জোর করে বন্ধ করে দেয় বা তাদের ডিভাইসটি বন্ধ করে দেয় তবে এটি কার্যকর হবে না it ।
ড্যারেন হিন্ডেরার

1
এই আচরণটি খুব বিরক্তিকর - যদি আপনার আবেদনের অনটার্মিনেট () পদ্ধতিটি কল করা হয় তবে আপনি পরিস্থিতি মার্জিতভাবে মোকাবেলা করতে পারলে এটি এত খারাপ হবে না।
ডিন ওয়াইল্ড

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

26

শুধু একটি নোট ..

যোগ করুন:

android:name=".Globals"

বা আপনি বিদ্যমান <application> ট্যাগটিতে আপনার সাবক্লাসটির নাম দিয়েছেন । আমি <application>ম্যানিফেস্টে আরও একটি ট্যাগ যুক্ত করার চেষ্টা করে চলেছি এবং এর ব্যতিক্রম পাব।


হাই, জিম্বল আমারও একই সমস্যা ছিল। আমার নিজের নিজস্ব <অ্যাপ্লিকেশন> ট্যাগও ছিল এবং যখন আমি অন্য <অ্যাপ্লিকেশন> ট্যাগ যুক্ত করার চেষ্টা করি তখন আপনার (ব্যতিক্রম বার্তা) মতো আমারও একই সমস্যা হয়েছিল। তবে আপনি যা উল্লেখ করেছেন আমি তা করেছি এবং এটি কার্যকর হয়নি। আমি অ্যান্ড্রয়েড যুক্ত করি: নাম = "। গ্লোবালক্লাস" আমার <অ্যাপ্লিকেশন> ট্যাগটিতে তবে এটি কার্যকর হয় না। আপনি কীভাবে এটি সমাধান করেছেন তা পুরোপুরি ব্যাখ্যা করতে পারবেন ??
সোনহজা

3
ভাল <ম্যানিফেস্ট> <অ্যাপ্লিকেশন অ্যান্ড্রয়েড: নাম = "। গ্লোবাল ডেটা"> << অ্যাপ্লিকেশন> </ ম্যানিফেস্ট>। খারাপ <ম্যানিফেস্ট >< অ্যাপ্লিকেশন> << অ্যাপ্লিকেশন> <অ্যাপ্লিকেশন অ্যান্ড্রয়েড: নাম = "। গ্লোবাল ডেটা"> </ অ্যাপ্লিকেশন> </ ম্যানিফেস্ট>
জিম্বল

13

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

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

সাবক্লাসটি alচ্ছিক; বেশিরভাগ অ্যাপ্লিকেশনগুলির একটির প্রয়োজন হবে না। সাবক্লাসের অভাবে অ্যান্ড্রয়েড বেস অ্যাপ্লিকেশন শ্রেণির উদাহরণ ব্যবহার করে।


13

এই জাতীয় বৈশ্বিক কাঠামোর সাথে নেটিভ স্মৃতি সংগ্রহ নিশ্চিত করার বিষয়ে কী?

ক্রিয়াকলাপগুলির এমন একটি onPause/onDestroy()পদ্ধতি রয়েছে যা ধ্বংসের ডাক দেয়, তবে অ্যাপ্লিকেশন শ্রেণির কোনও সমতুল্য নেই। অ্যাপ্লিকেশনটি মারা গেলে বা টাস্ক স্ট্যাকটি পটভূমিতে রাখলে বিশ্বব্যাপী কাঠামোগুলি (বিশেষত দেশীয় মেমরির উল্লেখ রয়েছে) আবর্জনা যথাযথভাবে সংগ্রহ করা হয় তা নিশ্চিত করার জন্য কোন ব্যবস্থাটি সুপারিশ করা হয়?


1
সুস্পষ্ট সমাধান হ'ল দেশীয় সম্পদের জন্য দায়ী আপনার অবজেক্টের জন্য ক্লোজযোগ্য ইন্টারফেস বাস্তবায়ন করা এবং এটি নিশ্চিত করে যে এগুলি একটি চেষ্টা-সংস্থান-সংক্রান্ত বিবৃতি বা অন্য কোনও কিছু দ্বারা পরিচালিত হয়েছে। সবচেয়ে খারাপ ক্ষেত্রে আপনি সর্বদা কোনও অবজেক্ট ফাইনালাইজার ব্যবহার করতে পারেন।
শীঘ্রই

5

ঠিক আপনার নীচের মতো একটি অ্যাপ্লিকেশন নাম নির্ধারণ করতে হবে যা কাজ করবে:

<application
  android:name="ApplicationName" android:icon="@drawable/icon">
</application>

4

যেমন উপরে আলোচনা করা হয়েছিল ওএস কোনও বিজ্ঞপ্তি ছাড়াই অ্যাপ্লিকেশনটিকে হত্যা করতে পারে (কোনও onDestroy ইভেন্ট নেই) তাই এই গ্লোবাল ভেরিয়েবলগুলি সংরক্ষণ করার কোনও উপায় নেই।

আপনার পূর্বনির্ধারিত স্ট্রাকচার্ড ভেরিয়েবলগুলি ব্যতীত ভাগ করা অগ্রাধিকারগুলি সমাধান হতে পারে (আমার ক্ষেত্রে ব্যবহারকারী ইতিমধ্যে যে আইডি পরিচালনা করেছেন সেগুলি সংরক্ষণ করার জন্য আমার কাছে পূর্ণসংখ্য অ্যারে ছিল)। SharedPreferences এ সমস্যাটি হ'ল প্রতিবারের মানগুলি প্রয়োজনীয়তার সাথে এই কাঠামোগুলি সংরক্ষণ এবং পুনরুদ্ধার করা শক্ত।

আমার ক্ষেত্রে আমার একটি ব্যাকগ্রাউন্ড সার্ভিস ছিল তাই আমি এই পরিবর্তনগুলিগুলিকে সেখানে স্থানান্তর করতে পারতাম এবং কারণ পরিষেবাটিতে Dডস্ট্রয় ইভেন্ট রয়েছে, আমি সেই মানগুলি সহজেই সংরক্ষণ করতে পারতাম।


onDestroy () এমনকি কোনও পরিষেবার জন্য ডেকে আনাও গ্যারান্টিযুক্ত নয়।
ওপেনজিএল ইএস

হ্যাঁ, এটি ঘটতে পারে তবে শুধুমাত্র সংকটময় পরিস্থিতিতে।
অ্যাডোরজান প্রিনজ

4

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

সুতরাং সঠিক উপায়টি সন্ধান করুন এবং সর্বোত্তম উপায় নেই।


3

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


2

<application>ম্যানিফেস্ট ফাইলটিতে অন্য ট্যাগ ব্যবহার করবেন না। বিদ্যমান ট্যাগটিতে কেবল একটি পরিবর্তন <application>করুন, এই লাইনটি যুক্ত করুন android:name=".ApplicationName"যেখানে ApplicationNameআপনার সাবক্লাসের নাম হবে (বিশ্বব্যাপী সংরক্ষণের জন্য ব্যবহার করুন), আপনি তৈরি করতে চলেছেন।

সুতরাং, অবশেষে ম্যানিফেস্ট ফাইলে আপনার এক এবং কেবল <application> ট্যাগটি দেখতে হবে: -

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat.NoActionBar"
        android:name=".ApplicationName"
        >

1

আপনি ইন্টেন্টস, স্ক্লাইট বা ভাগ করা পছন্দগুলি ব্যবহার করতে পারেন। এটি যখন ডকুমেন্টস, ফটোগুলি এবং ভিডিওগুলির মতো মিডিয়া স্টোরেজে আসে, আপনি তার পরিবর্তে নতুন ফাইল তৈরি করতে পারেন।


1

আপনি দুটি পদ্ধতির সাহায্যে এটি করতে পারেন:

  1. অ্যাপ্লিকেশন ক্লাস ব্যবহার করে
  2. ভাগ করা পছন্দগুলি ব্যবহার করা

  3. অ্যাপ্লিকেশন ক্লাস ব্যবহার করে

উদাহরণ:

class SessionManager extends Application{

  String sessionKey;

  setSessionKey(String key){
    this.sessionKey=key;
  }

  String getSessisonKey(){
    return this.sessionKey;
  }
}

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

@override 
public void onCreate (Bundle savedInstanceState){
  // you will this key when first time login is successful.
  SessionManager session= (SessionManager)getApplicationContext();
  String key=getSessisonKey.getKey();
  //Use this key to identify whether session is alive or not.
}

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

  1. ভাগ করা পছন্দগুলি ব্যবহার করে।

    String MYPREF="com.your.application.session"
    
    SharedPreferences pref= context.getSharedPreferences(MyPREF,MODE_PRIVATE);
    
    //Insert key as below:
    
    Editot editor= pref.edit();
    
    editor.putString("key","value");
    
    editor.commit();
    
    //Get key as below.
    
    SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
    
    String key= getResources().getString("key");

0

ক্রিয়াকলাপের ফলাফল পুনরায় শুরু করার আগে ডাকা হয়। সুতরাং আপনি লগইন চেকটিকে পুনরায় শুরুতে সরান এবং সেকোমড ক্রিয়াকলাপ কোনও ইতিবাচক ফলাফল ফিরে আসার পরে আপনার দ্বিতীয় লগইনটি ব্লক করা যেতে পারে। পুনরায় শুরুতে প্রতিবার কল করা হয় তাই এটি প্রথমবারের মতো না ডাকা নিয়ে উদ্বেগ নেই।


0

সাবক্লাসিংয়ের পদ্ধতিটি বারাকাস কাঠামোর দ্বারাও ব্যবহৃত হয়েছে। আমার দৃষ্টিকোণ থেকে সাবক্লাসিং অ্যাপ্লিকেশনটির উদ্দেশ্য ছিল অ্যান্ড্রয়েডের জীবনকাল নিয়ে কাজ করা; এটি কোনও অ্যাপ্লিকেশন ধারক করে। তারপরে গ্লোবাল থাকার পরিবর্তে, আমি এই প্রসঙ্গে শিমটি রেজিস্ট্রেশন করি যাতে তাদের প্রসঙ্গে বিন্যাসযোগ্য কোনও শ্রেণিতে ইনকিউশন দেওয়া যায়। প্রতিটি ইনজেকশন করা শিমের দৃষ্টান্তটি আসলে একটি সিঙ্গলটন।

বিশদ জন্য এই উদাহরণ দেখুন

আপনি যদি আরও অনেক কিছু করতে পারেন তবে ম্যানুয়াল কেন কাজ করবেন?


0
class GlobaleVariableDemo extends Application {

    private String myGlobalState;

    public String getGlobalState(){
     return myGlobalState;
    }
    public void setGlobalState(String s){
     myGlobalState = s;
    }
}

class Demo extends Activity {

@Override
public void onCreate(Bundle b){
    ...
    GlobaleVariableDemo appState = ((GlobaleVariableDemo)getApplicationContext());
    String state = appState.getGlobalState();
    ...
    }
}

0

আপনি ক্লাস প্রসারিত একটি শ্রেণি তৈরি করতে পারেন Applicationএবং তারপরে আপনার পরিবর্তনশীলটিকে সেই শ্রেণীর ক্ষেত্র হিসাবে ঘোষণা করুন এবং এর জন্য গেটর পদ্ধতি সরবরাহ করুন।

public class MyApplication extends Application {
    private String str = "My String";

    synchronized public String getMyString {
        return str;
    }
}

এবং তারপরে আপনার ক্রিয়াকলাপে সেই পরিবর্তনশীলটি অ্যাক্সেস করতে, এটি ব্যবহার করুন:

MyApplication application = (MyApplication) getApplication();
String myVar = application.getMyString();
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.