android ডায়ালগ নিক্ষেপণ "পেতে উইন্ডোতে যোগ করতে অক্ষম-টোকেন নাল একটি অ্যাপ্লিকেশনের জন্য নয়" getAplication() হিসাবে প্রসঙ্গ হিসাবে




android-alertdialog android-context (19)

আপনি যদি একটি ফ্যাগমেন্ট ব্যবহার করেন এবং অ্যালার্টডিয়ালগ / টোস্ট বার্তা ব্যবহার করেন তবে প্রসঙ্গ প্যারামিটারে getActivity () ব্যবহার করুন।

এটার মত

ProgressDialog pdialog;
pdialog = new ProgressDialog(getActivity());
pdialog.setCancelable(true);
pdialog.setMessage("Loading ....");
pdialog.show();

আমার ক্রিয়াকলাপ একটি সতর্কতা ডায়ালগ তৈরি করার চেষ্টা করছে যার জন্য একটি প্যারামিটার হিসাবে একটি কনটেক্সট প্রয়োজন। আমি ব্যবহার করলে এটি প্রত্যাশিত হিসাবে কাজ করে:

AlertDialog.Builder builder = new AlertDialog.Builder(this);

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

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

কিন্তু AlertDialog() neither getApplicationContext() বা getApplication() কোন প্রসঙ্গ হিসাবে গ্রহনযোগ্য নয়, এটি ব্যতিক্রমটিকে ছুঁড়ে ফেলে দেয়:

"উইন্ডো যোগ করতে অক্ষম - টোকেন নাল একটি অ্যাপ্লিকেশনের জন্য নয়"

প্রতি রেফারেন্স: 1 , 2 , 3 , ইত্যাদি

সুতরাং, এটি কি আসলেই "বাগ" হিসাবে বিবেচনা করা উচিত, যেহেতু আমাদের কাছে আনুষ্ঠানিকভাবে Activity.getApplication() ব্যবহার করার পরামর্শ দেওয়া হয়েছে এবং এটি বিজ্ঞাপনের মতো কাজ করে না?

জিম


this ব্যবহার করে আমার জন্য কাজ করে না, কিন্তু MyActivityName.thisMyActivityName.this করেছিল। এই কাজ করতে পারে না যারা এই সাহায্য করে আশা করি।



MyDialog md = new MyDialog(MyActivity.this.getParent());


যখন আপনি বলেছিলেন যে আপনি সমস্যাটির সঠিকভাবে সনাক্ত করেছেন "... AlertDialog () পেতে না AppplicationContext () বা getAplication () একটি প্রসঙ্গ হিসাবে গ্রহণযোগ্য, এটি ব্যতিক্রমটিকে ছুঁড়ে ফেলে দেয় কারণ 'উইন্ডো - টোকেন নাল যুক্ত করতে অক্ষম নয় একটি দরখাস্ত'"

একটি ডায়ালগ তৈরি করার জন্য, আপনার একটি কার্যকলাপ কনটেক্সট বা একটি পরিষেবা প্রসঙ্গ প্রয়োজন , কোনও অ্যাপ্লিকেশন কনটেক্সট নয় (getApplicationContext () এবং get appplication () উভয়টি অ্যাপ্লিকেশন কনটেক্সটটি ফেরত দিন)।

এখানে আপনি কীভাবে কার্যকলাপ প্রসঙ্গটি পাবেন :

(1) একটি ক্রিয়াকলাপ বা একটি পরিষেবা মধ্যে:

AlertDialog.Builder builder = new AlertDialog.Builder(this);

(2) একটি ফ্র্যাগমেন্টে: AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

মেমরি লিক একটি সমস্যা যা "এই" রেফারেন্সের অন্তর্নিহিত নয়, যা একটি বস্তুর নিজ নিজ রেফারেন্স (অর্থাত্ বস্তুর তথ্য সঞ্চয় করার জন্য প্রকৃত বরাদ্দকৃত মেমরির রেফারেন্স)। বরাদ্দকৃত মেমরির কার্যকর জীবনকাল অতিক্রম করার পরে গার্বেজ কালেক্টর (জিসি) মুক্ত হতে অক্ষম যে কোন বরাদ্দকৃত মেমরির সাথে এটি ঘটে।

সর্বাধিক সময়, যখন একটি পরিবর্তনশীল সুযোগ ছাড়িয়ে যায়, মেমরি GC দ্বারা পুনরায় দাবি করা হবে। যাইহোক, একটি পরিবর্তনশীল দ্বারা অনুষ্ঠিত একটি বস্তুর রেফারেন্স যখন মেমরি লিক ঘটতে পারে, "এক্স" বলতে, অবজেক্ট তার দরকারী জীবদ্দশায় অতিক্রম করেছে পরেও অব্যাহত। বরাদ্দকৃত মেমরিটি "x" এটিকে একটি রেফারেন্স ধরে রাখার জন্য যতক্ষন পর্যন্ত না হারিয়ে যাবে, ততক্ষণ GC যতক্ষণ স্মৃতিটি রেফারেন্স করা হচ্ছে ততক্ষণ পর্যন্ত জিসি মেমরি মুক্ত করবে না । কখনও কখনও, মেমরি লিক বরাদ্দ মেমরির রেফারেন্স একটি চেইন কারণে স্পষ্ট নয়। এ ক্ষেত্রে, মেমরির সমস্ত রেফারেন্স সরানো না হওয়া পর্যন্ত জিসি মেমরি মুক্ত করবে না।

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


অথবা অন্য একটি সম্ভাবনা অনুসরণ হিসাবে ডায়ালগ তৈরি করা হয়:

final Dialog dialog = new Dialog(new ContextThemeWrapper(
            this, R.style.MyThemeDialog));

আপনি যদি একটি AlertDialog / Toast ব্যবহার করেন এবং AlertDialog / Toast বার্তা ব্যবহার করে, প্রসঙ্গ প্যারামিটারে getActivity() ব্যবহার করুন।

আমার জন্য কাজ।

চিয়ার্স!


নতুন AlertDialog.Builder(getParent()); মত প্রসঙ্গের যুক্তি স্থানটিতে getParent() চেষ্টা করুন AlertDialog.Builder(getParent()); এটা কাজ করবে আশা করি, এটা আমার জন্য কাজ করে।


getApplicationContext() এর পরিবর্তে, getApplicationContext() ব্যবহার করুন।


আপনি getApplicationContext() ব্যবহার চালিয়ে যেতে পারেন, তবে ব্যবহারের আগে, আপনাকে এই পতাকা যুক্ত করতে হবে: dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT) , এবং ত্রুটিটি দেখানো হবে না।

আপনার ম্যানিফেস্টে নিম্নলিখিত অনুমতি যোগ করুন:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

কথোপকথনের অধীনে ব্যবহার করা হবে যা একটি কার্যকলাপ প্রসঙ্গ ব্যবহার করার চেষ্টা করুন। কিন্তু যখন আপনি "এই" শব্দটি ব্যবহার করেন তখন সতর্ক হোন কারণ এটি সর্বদা কাজ করবে না।

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

আমি কোনো তথ্য থেকে কিন্তু এই চেষ্টা করে এই তথ্য খুঁজে না। এটি দৃঢ় পটভূমি ছাড়া আমার সমাধান, যদি ভাল জ্ঞানের সাথে যে কেউ, মন্তব্য করতে বিনা দ্বিধায়।


কার্যকলাপ শুধু ব্যবহার করুন:

MyActivity.this

Fragment মধ্যে:

getActivity();

আমি ProgressDialog একটি getActivity().getApplicationContext() ব্যবহার করছিলাম এবং getActivity().getApplicationContext() কে কনস্ট্রাকটর প্যারামিটার হিসাবে পাস করতে এই ত্রুটিটি getActivity().getApplicationContext() । এটি getActivity().getBaseContext() করার জন্য getActivity().getBaseContext() কাজ করে না।

সমাধান যে আমার জন্য কাজ ছিল getActivity() ; অর্থাত

progressDialog = new ProgressDialog(getActivity());


একটি কনট্রাস্টারের মাধ্যমে আমার প্রেক্ষাপটটি একটি খণ্ডে প্রদর্শিত একটি কাস্টম অ্যাডাপ্টারের উপর পাঠাতে হয়েছিল এবং getAplicationContext () এর সাথে এই সমস্যাটি ছিল। আমি এটা দিয়ে সমাধান:

this.getActivity().getWindow().getContext() টুকরাগুলির মধ্যে ' onCreate কলব্যাক'।


লিটল হ্যাক: আপনি জি.সি. দ্বারা আপনার ক্রিয়াকলাপকে ধ্বংস করতে বাধা দিতে পারেন (আপনাকে এটি করা উচিত নয়, তবে এটি কিছু পরিস্থিতিতে সাহায্য করতে পারে। প্রসঙ্গ সেট করতে ভুলবেন না যখন এটি আর প্রয়োজন হয় না তখন contextForDialog null করতে):

public class PostActivity extends Activity  {
    ...
    private Context contextForDialog = null;
    ...
    public void onCreate(Bundle savedInstanceState) {
        ...
        contextForDialog = this;
    }
    ...
    private void showAnimatedDialog() {
        mSpinner = new Dialog(contextForDialog);
        mSpinner.setContentView(new MySpinner(contextForDialog));
        mSpinner.show();
    }
    ...
}

আপনার ডায়লগটি "দীর্ঘস্থায়ী বস্তু নয় যা একটি প্রসঙ্গের প্রয়োজন" হওয়া উচিত নয়। ডকুমেন্টেশন বিভ্রান্তিকর। মূলত যদি আপনি কিছু ভালো করেন:

static Dialog sDialog;

( স্ট্যাটিক নোট করুন)

তারপর একটি কার্যকলাপ কোথাও আপনি কি

 sDialog = new Dialog(this);

আপনি সম্ভবত একটি ঘূর্ণন বা অনুরূপ সময় কার্যকলাপটি ধ্বংস করবে যে মূল কার্যকলাপ leaking হবে। (আপনি ডিস্ট্রয়েলে পরিষ্কার না হওয়া পর্যন্ত, কিন্তু সেই ক্ষেত্রে আপনি সম্ভবত ডায়ালগ অবজেক্টটিকে স্ট্যাটিক করবেন না)

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

Dialog mDialog;

...

mDialog = new Dialog(this);

জরিমানা এবং কার্যকলাপটি লিক করতে হবে না কারণ এটি স্ট্যাটিক নয় কারন mDialog কার্যকলাপের সাথে মুক্ত হবে।


ভবিষ্যতে পাঠকদের জন্য, এই সাহায্য করা উচিত:

public void show() {
    if(mContext instanceof Activity) {
        Activity activity = (Activity) mContext;
        if (!activity.isFinishing() && !activity.isDestroyed()) {
            dialog.show();
        }
    }
}

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

যদিও আমি যে কোন জায়গায় স্পষ্টভাবে উল্লেখ করা নেই বলে মনে হচ্ছে, মনে হচ্ছে আপনি এই কাজটি কেবল OnClickHandlers এ কথোপকথনটি পাস করেছেন।


যোগ

dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

এবং

ম্যানিফেস্টে "android.permission.SYSTEM_ALERT_WINDOW"/>

এটা এখন আমার জন্য কাজ করে। এমনকি বন্ধ এবং আবেদন খুলতে পরে, যে সময়ে ত্রুটি আমাকে দিয়েছেন।





builder