অ্যাসিঙ্কটাস্ক আসলেই ধারণাগতভাবে ত্রুটিযুক্ত বা আমি কিছু হারিয়ে যাচ্ছি?


264

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

সমস্যাটিও তাই AsyncTask। ডকুমেন্টেশন অনুযায়ী এটি

"থ্রেড এবং / অথবা হ্যান্ডলারগুলি পরিচালনা না করে পটভূমি অপারেশন করতে এবং ইউআই থ্রেডে ফলাফল প্রকাশের অনুমতি দেয়।"

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

কারণটি সুস্পষ্ট: যদি ক্রিয়াকলাপটি ধ্বংস হয়ে যায় যা কার্যকে উদ্বুদ্ধ করে? এটি সর্বদা ঘটতে পারে, যেমন আপনি পর্দা উল্টিয়েছেন li যদি টাস্কটি এটি তৈরি করা প্রসঙ্গে একটি রেফারেন্স রাখে, আপনি কেবল একটি অকেজো প্রসঙ্গ অবজেক্ট ধরে থাকবেন না (উইন্ডোটি ধ্বংস হয়ে যাবে এবং কোনও UI ইন্টারঅ্যাকশন ব্যতিক্রম সহ ব্যর্থ হবে!), আপনি এমনকি কোনও ঝুঁকি তৈরির ঝুঁকি তৈরি করবেন মেমরি লিক.

আমার যুক্তি এখানে ত্রুটিযুক্ত না হলে এটি অনুবাদ করে: onPostExecute()সম্পূর্ণরূপে অকেজো, কারণ আপনার যদি কোনও প্রসঙ্গে অ্যাক্সেস না থাকে তবে এই পদ্ধতিটি ইউআই থ্রেডে চালানো ভাল কি? আপনি এখানে অর্থবহ কিছু করতে পারবেন না।

একটি কাজের সমাধান হ'ল AsyncTask এ প্রসঙ্গে দৃষ্টান্তগুলি না পাঠানো, তবে একটি Handlerউদাহরণ। এটি কাজ করে: যেহেতু কোনও হ্যান্ডলার প্রসঙ্গ এবং কার্যটি আলগাভাবে আবদ্ধ করে, তাই আপনি ফাঁস (ডান?) ঝুঁকি না নিয়েই তাদের মধ্যে বার্তা বিনিময় করতে পারেন। তবে এর অর্থ এই হবে যে অ্যাসিঙ্কটাস্কের ভিত্তিটি হ'ল হ্যান্ডলারদের আপনার বিরক্ত করার দরকার নেই, এটি ভুল। এটি হ্যান্ডলারের সাথে আপত্তিজনক বলে মনে হচ্ছে, যেহেতু আপনি একই থ্রেডে বার্তা প্রেরণ এবং গ্রহণ করছেন (আপনি এটি ইউআই থ্রেডটিতে তৈরি করেন এবং এটি মাধ্যমে পোস্টপেক্সেক্সিউটে () যা ইউআই থ্রেডেও কার্যকর করা হয়)।

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

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

তবুও, এটি একটি জটিল কাজ এবং এটি একটি চমত্কার অনুপ্রেরণীয় পদ্ধতির তৈরি করে কিছু ড্রড-ফু গ্রন্থাগার ক্লাসের উপ-শ্রেণীর প্রয়োজন।

এখন আমি কেবল জানতে চাই: আমি কি কেবলমাত্র কিছুটা হারিয়েছি বা অ্যাসিঙ্কটাস্ক আসলেই পুরোপুরি ত্রুটিযুক্ত? আপনার অভিজ্ঞতাগুলি এটির সাথে কীভাবে কাজ করছে? আপনি কীভাবে এই সমস্যার সমাধান করলেন?

আপনার ইনপুট জন্য ধন্যবাদ।


1
আপনি যদি কৌতূহলী হন তবে আমরা সম্প্রতি ইগনিটেডসাইঙ্কটাস্ক নামে পরিচিত ইগনিশন কোর লাইব্রেরিতে একটি ক্লাস যুক্ত করেছি, যা নীচে ডায়ান্ন দ্বারা বর্ণিত সংযোগ / সংযোগ বিচ্ছিন্ন প্যাটার্নটি ব্যবহার করে সমস্ত কলব্যাকগুলিতে টাইপ-নিরাপদ প্রসঙ্গ অ্যাক্সেসের জন্য সমর্থন যোগ করে। এটি ব্যতিক্রম ছোঁড়াতে এবং একটি পৃথক কলব্যাকে তাদের পরিচালনা করতেও অনুমতি দেয়। Github.com/kaeppler/ignition-core/blob/master/src/com/github/…
ম্যাথিয়াস



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

উত্তর:


86

কিভাবে ভালো কিছু সম্পর্কে:

class MyActivity extends Activity {
    Worker mWorker;

    static class Worker extends AsyncTask<URL, Integer, Long> {
        MyActivity mActivity;

        Worker(MyActivity activity) {
            mActivity = activity;
        }

        @Override
        protected Long doInBackground(URL... urls) {
            int count = urls.length;
            long totalSize = 0;
            for (int i = 0; i < count; i++) {
                totalSize += Downloader.downloadFile(urls[i]);
                publishProgress((int) ((i / (float) count) * 100));
            }
            return totalSize;
        }

        @Override
        protected void onProgressUpdate(Integer... progress) {
            if (mActivity != null) {
                mActivity.setProgressPercent(progress[0]);
            }
        }

        @Override
        protected void onPostExecute(Long result) {
            if (mActivity != null) {
                mActivity.showDialog("Downloaded " + result + " bytes");
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mWorker = (Worker)getLastNonConfigurationInstance();
        if (mWorker != null) {
            mWorker.mActivity = this;
        }

        ...
    }

    @Override
    public Object onRetainNonConfigurationInstance() {
        return mWorker;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mWorker != null) {
            mWorker.mActivity = null;
        }
    }

    void startWork() {
        mWorker = new Worker(this);
        mWorker.execute(...);
    }
}

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

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

8
সত্য, তবে এটি এখনও শেষ সমস্যার সমাধান করতে পারে না: কল্পনা করুন যে টাস্কটি ইন্টারনেট থেকে কিছু ডাউনলোড করে। এই পদ্ধতির ব্যবহার করে, যদি আপনি টাস্কটি চলাকালীন 3 বার স্ক্রিনটি ফ্লিপ করেন তবে এটি প্রতিটি পর্দার ঘোরার সাথে পুনরায় শুরু হবে এবং শেষ ব্যতীত প্রতিটি কাজই তার ফলাফলটিকে ফেলে দেয় কারণ এর ক্রিয়াকলাপটি রেফারেন্স বাতিল।
ম্যাথিয়াস

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

4
এটি অবিশ্বাস্যরূপে সহায়ক ছিল, ধন্যবাদ ডায়ান! আমি আশা করি ডকুমেন্টেশনটি প্রথম স্থানে যেমন ভাল হয় তেমন।
ম্যাথিয়াস

20

কারণটি সুস্পষ্ট: যদি ক্রিয়াকলাপটি ধ্বংস হয়ে যায় যা কার্যকে উদ্বুদ্ধ করে?

ম্যানুয়ালি থেকে কার্যকলাপ অসংযুক্ত AsyncTaskমধ্যে onDestroy()। ম্যানুয়ালি নতুন কার্যকলাপ পুনরায় সংযুক্ত AsyncTaskমধ্যে onCreate()। এর জন্য হয় স্থিতিশীল অভ্যন্তর শ্রেণি বা একটি মানক জাভা শ্রেণি, এবং সম্ভবত 10 টি লাইন কোডের প্রয়োজন।


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

10
@ মাথিয়াস: আমি স্থির রেফারেন্স ব্যবহার করতে বলিনি। আমি বললাম স্ট্যাটিক ইনার ক্লাস ব্যবহার করতে। উভয়ের নামে "স্থির" থাকা সত্ত্বেও যথেষ্ট পার্থক্য রয়েছে।
কমন্সওয়্যার


5
আমি দেখতে পাচ্ছি - তারা এখানে কীটি হ'ল getLastNonConfigrationInstance (), স্থির অভ্যন্তর শ্রেণি নয়। একটি স্থিতিশীল অভ্যন্তরীণ বর্গ তার বাহ্যিক শ্রেণীর জন্য কোনও অন্তর্নিহিত রেফারেন্স রাখে না তাই এটি শব্দার্থগতভাবে একটি সরল পাবলিক শ্রেণীর সমতুল্য। কেবলমাত্র একটি সতর্কতা: #RetainNonfigrationInstance () কোনও ক্রিয়াকলাপ বাধাগ্রস্থ হলে কল করার নিশ্চয়তা দেয় না (একটি বাধাও একটি ফোন কল হতে পারে), সুতরাং আপনাকে সত্যিকারের জন্য দৃS়তার জন্য নিজের কাজটি onSaveInstanceState () এ পার্সেল করতে হবে d সমাধান। তবে তবুও, দুর্দান্ত ধারণা।
ম্যাথিয়াস

7
উম ... onRetainNonCfigrationInstance () সর্বদা বলা হয় যখন ক্রিয়াকলাপটি ধ্বংস এবং পুনরায় তৈরি হওয়ার প্রক্রিয়াতে থাকে। এটি অন্য সময়ে কল করার কোনও মানে নেই। যদি অন্য ক্রিয়াকলাপে একটি স্যুইচ ঘটে, তবে বর্তমান ক্রিয়াকলাপটি থামা / থামানো হয়েছে, তবে এটি ধ্বংস হয় না, সুতরাং অ্যাসিঙ্ক কার্যটি একই ক্রিয়াকলাপ উদাহরণটি চালিয়ে যাওয়া এবং ব্যবহার চালিয়ে যেতে পারে। যদি এটি শেষ হয়ে যায় এবং একটি কথোপকথন প্রদর্শন করে, ডায়ালগটি সেই ক্রিয়াকলাপের অংশ হিসাবে সঠিকভাবে প্রদর্শিত হবে এবং এভাবে তারা ক্রিয়াকলাপে ফিরে না আসা পর্যন্ত ব্যবহারকারীকে না দেখায়। আপনি AsyncTask কোনও বান্ডলে রাখতে পারবেন না।
30:50

15

দেখে মনে হচ্ছে AsyncTaskএটি কেবল ধারণামূলক ত্রুটিযুক্ত না থেকে কিছুটা বেশি । এটি সামঞ্জস্যের সমস্যাগুলির দ্বারা অকার্যকর। অ্যান্ড্রয়েড ডক্স পড়ুন:

প্রথম উপস্থাপিত হওয়ার পরে, AsyncTasks একক পটভূমির থ্রেডে সিরিয়ালি কার্যকর করা হয়েছিল। ডোনট দিয়ে শুরু করে, এটি থ্রেডের একটি পুলে পরিবর্তন করা হয়েছিল যাতে একাধিক কাজ সমান্তরালভাবে পরিচালিত হতে পারে। HONEYCOMB শুরু করে, সমান্তরাল মৃত্যুর ফলে কার্যকর অ্যাপ্লিকেশন ত্রুটিগুলি এড়াতে একক থ্রেডে কার্য সম্পাদন করা হবে। আপনি যদি সত্যই সমান্তরাল সম্পাদন করতে চান তবে আপনি executeOnExecutor(Executor, Params...) এই পদ্ধতির সংস্করণটি এর সাথে ব্যবহার করতে পারেনTHREAD_POOL_EXECUTOR ; তবে, এর ব্যবহার সম্পর্কে সতর্কতার জন্য সেখানে মন্তব্য দেখুন।

উভয় executeOnExecutor()এবং THREAD_POOL_EXECUTORকরছে এপিআই স্তর 11 যোগ করা হয়েছে (অ্যান্ড্রয়েড 3.0.x, মউচাক)।

এর অর্থ হ'ল যদি আপনি AsyncTaskদুটি ফাইল ডাউনলোড করতে দুটি গুলি তৈরি করেন তবে প্রথম ডাউনলোড শেষ না হওয়া পর্যন্ত ২ য় ডাউনলোড শুরু হবে না। যদি আপনি দুটি সার্ভারের মাধ্যমে চ্যাট করেন এবং প্রথম সার্ভারটি ডাউন হয়ে যায় তবে প্রথমবারের সাথে সংযোগ দেওয়ার আগে আপনি দ্বিতীয়টির সাথে সংযোগ স্থাপন করবেন না। (আপনি যদি নতুন এপিআই 11 বৈশিষ্ট্যগুলি ব্যবহার না করেন তবে অবশ্যই এটি আপনার কোডটিকে ২.x এর সাথে বেমানান করে তুলবে)।

এবং আপনি যদি 2.x এবং 3.0+ উভয়কেই লক্ষ্য করতে চান তবে স্টাফটি সত্যই জটিল trick

এছাড়াও, ডক্সগুলি বলে:

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


12

সম্ভবত গুগল সহ আমরা সকলেই এমভিসি দৃষ্টিকোণ AsyncTaskথেকে অপব্যবহার করছি ।

একটি ক্রিয়াকলাপ একটি নিয়ামক , এবং নিয়ামকটির এমন ক্রিয়াকলাপ শুরু করা উচিত নয় যা দৃশ্যকে বহির্ভূত করতে পারে । অর্থাৎ, অ্যাসিঙ্কটাস্কগুলি মডেল থেকে ব্যবহার করা উচিত , এমন একটি শ্রেণীর থেকে যা ক্রিয়াকলাপের জীবনচক্রের সাথে আবদ্ধ নয় - মনে রাখবেন যে ক্রিয়াকলাপগুলি ঘূর্ণনের সময় নষ্ট হয়ে যায়। (হিসেবে দেখুন , তাই না সাধারণত প্রোগ্রাম শ্রেণীর যেমন android.widget.Button থেকে উদ্ভূত না, কিন্তু আপনি যা করতে পারেন। সাধারণত, শুধু আপনার সম্পর্কে কি দেখুন XML হয়।)

অন্য কথায়, ক্রিয়াকলাপগুলির পদ্ধতিগুলিতে অ্যাসিঙ্কটাস্ক ডেরিভেটিভগুলি স্থাপন করা ভুল। OTOH, যদি আমাদের ক্রিয়াকলাপগুলিতে অ্যাসিঙ্কটাস্ক ব্যবহার না করা হয় তবে অ্যাসিঙ্কটাস্ক এর আকর্ষণ হারিয়ে ফেলে: এটি দ্রুত এবং সহজ সমাধান হিসাবে বিজ্ঞাপন হিসাবে ব্যবহৃত হত।


5

আমি নিশ্চিত নই যে এটি সত্য যে আপনি অ্যাসিঙ্কটাস্কের কোনও প্রসঙ্গে একটি রেফারেন্স সহ একটি মেমরি ফুটো ঝুঁকিপূর্ণ।

এগুলি প্রয়োগের স্বাভাবিক উপায় হ'ল ক্রিয়াকলাপের কোনও পদ্ধতির আওতায় একটি নতুন অ্যাসিঙ্কটাস্ক উদাহরণ তৈরি করা। সুতরাং যদি ক্রিয়াকলাপটি ধ্বংস হয়ে যায়, তবে একবার অ্যাসিঙ্কটাস্ক সম্পূর্ণ হলে এটি কি অ্যাক্সেসযোগ্য এবং তারপরে আবর্জনা সংগ্রহের জন্য যোগ্য হবে না? সুতরাং ক্রিয়াকলাপের রেফারেন্স কোনও বিষয় নয় কারণ অ্যাসিঙ্কটাস্ক নিজেই এটি ঘিরে রাখবে না।


2
সত্য - তবে যদি কাজটি অনির্দিষ্টকালের জন্য বন্ধ করে দেয়? কার্যগুলি ব্লকিং অপারেশনগুলি সম্পাদন করে বোঝানো হয়, সম্ভবত এমনগুলিও যা কখনও শেষ হয় না। সেখানে আপনার স্মৃতি ফুটো আছে।
ম্যাথিয়াস

1
কোনও কর্মী যা অন্তহীন লুপে কিছু সম্পাদন করে বা এমন কিছু যা কেবল লক করে থাকে যেমন একটি আই / ও অপারেশন।
ম্যাথিয়াস

2

আপনার ক্রিয়াকলাপের উপর সপ্তাহের রেফারেন্স রাখা আরও দৃust় হবে:

public class WeakReferenceAsyncTaskTestActivity extends Activity {
    private static final int MAX_COUNT = 100;

    private ProgressBar progressBar;

    private AsyncTaskCounter mWorker;

    @SuppressWarnings("deprecation")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task_test);

        mWorker = (AsyncTaskCounter) getLastNonConfigurationInstance();
        if (mWorker != null) {
            mWorker.mActivity = new WeakReference<WeakReferenceAsyncTaskTestActivity>(this);
        }

        progressBar = (ProgressBar) findViewById(R.id.progressBar1);
        progressBar.setMax(MAX_COUNT);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_async_task_test, menu);
        return true;
    }

    public void onStartButtonClick(View v) {
        startWork();
    }

    @Override
    public Object onRetainNonConfigurationInstance() {
        return mWorker;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mWorker != null) {
            mWorker.mActivity = null;
        }
    }

    void startWork() {
        mWorker = new AsyncTaskCounter(this);
        mWorker.execute();
    }

    static class AsyncTaskCounter extends AsyncTask<Void, Integer, Void> {
        WeakReference<WeakReferenceAsyncTaskTestActivity> mActivity;

        AsyncTaskCounter(WeakReferenceAsyncTaskTestActivity activity) {
            mActivity = new WeakReference<WeakReferenceAsyncTaskTestActivity>(activity);
        }

        private static final int SLEEP_TIME = 200;

        @Override
        protected Void doInBackground(Void... params) {
            for (int i = 0; i < MAX_COUNT; i++) {
                try {
                    Thread.sleep(SLEEP_TIME);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.d(getClass().getSimpleName(), "Progress value is " + i);
                Log.d(getClass().getSimpleName(), "getActivity is " + mActivity);
                Log.d(getClass().getSimpleName(), "this is " + this);

                publishProgress(i);
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            if (mActivity != null) {
                mActivity.get().progressBar.setProgress(values[0]);
            }
        }
    }

}

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

1
আপনার কি রবস্পাইস এ নজর দেওয়া হয়েছে? github.com/octo-online/robospice । আমি বিশ্বাস করি যে এই সিস্টেমটি আরও উন্নত।
স্নিকোলস

প্রথম পৃষ্ঠায় স্যাম্পল কোডটি দেখে মনে হচ্ছে এটি একটি প্রসঙ্গ রেফারেন্স ফাঁস করছে (একটি অভ্যন্তরীণ শ্রেণি বাইরের শ্রেণীর একটি অন্তর্নিহিত রেফারেন্স রাখে)) নিশ্চিত নয় !!
ম্যাথিয়াস

@ মাথিয়াস, আপনি ঠিক বলেছেন, এজন্যই আমি একটি স্থিতিশীল অভ্যন্তর শ্রেণীর প্রস্তাব রাখি যা ক্রিয়াকলাপের উপর দুর্বল রেফারেন্স রাখবে।
Snicolas

1
@ মাথিয়াস, আমি বিশ্বাস করি এটি বিষয় ছাড়াই শুরু হবে। তবে লোডাররা বাক্সের বাইরে যেমন ক্যাশ প্রদান করে না, তত বেশি হ'ল, লোডাররা আমাদের লাইবের চেয়ে বেশি ভার্জোজ থাকে। প্রকৃতপক্ষে তারা বেশ ভাল কার্সারগুলি পরিচালনা করে তবে নেটওয়ার্কিংয়ের জন্য, ক্যাশে এবং একটি পরিষেবাদির উপর ভিত্তি করে একটি ভিন্ন পদ্ধতির জন্য আরও উপযুক্ত। দেখুন neilgoodman.net/2011/12/26/... অংশ 1 & 2
Snicolas

1

কেন কেবল onPause()নিজস্ব ক্রিয়াকলাপে পদ্ধতিটিকে ওভাররাইড করে AsyncTaskসেখান থেকে বাতিল করবেন না?


এটি সেই কাজটি কি করছে তার উপর নির্ভর করে। যদি এটি কেবল কিছু ডেটা লোড করে / পড়ে, তবে এটি ঠিক আছে। তবে যদি এটি কোনও রিমোট সার্ভারে কিছু ডেটার স্থিতি পরিবর্তন করে তবে আমরা টাস্কটিকে শেষ পর্যন্ত চালানোর ক্ষমতা দিতে পছন্দ করব।
ভিট খুডেনকো

@ আর্মিমেড এবং আমি এটি গ্রহণ করি যদি আপনি ইউআই থ্রেডটি ধরে রাখেন তবে onPauseএটি অন্য কোথাও ধরে রাখার মতোই খারাপ? অর্থাৎ আপনি একটি এএনআর পেতে পারেন?
জেফ এক্সেলরড

ঠিক। আমরা ইউআই থ্রেডটি ব্লক করতে পারি না (এটি onPauseঅন্যথায় বা অন্য কোনও বিষয় হোন) কারণ আমরা একটি এএনআর পাওয়ার ঝুঁকি নিয়ে থাকি।
ভিট খুডেনকো

1

আপনি একেবারে ঠিক বলেছেন - এজন্য ডেটা আনতে ক্রিয়াকলাপগুলিতে অ্যাসিঙ্ক কাজগুলি বা লোডারগুলি ব্যবহার করা থেকে দূরে একটি আন্দোলন গতি অর্জন করছে। নতুন উপায়গুলির মধ্যে একটি হ'ল ভল্লি ফ্রেমওয়ার্ক ব্যবহার করা যা ডেটা প্রস্তুত হওয়ার পরে প্রয়োজনীয়ভাবে কলব্যাক সরবরাহ করে - এমভিসি মডেলের সাথে অনেক বেশি সামঞ্জস্যপূর্ণ। ভলিকে গুগল আই / ও ২০১৩ সালে জনপ্রিয় করা হয়েছিল more কেন বেশি লোকেরা এ সম্পর্কে অবগত নয় তা নিশ্চিত নয়।


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

0

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


1
ঠিক আছে, আপনার ফোর্স ক্লোজটি সম্ভবত আমি যে সমস্যার কথা বলেছিলাম তার কারণ: আপনি এমন একটি প্রসঙ্গে উল্লেখ করার চেষ্টা করেছিলেন যা সুযোগের বাইরে চলে গিয়েছিল (যেমন এর উইন্ডোটি ধ্বংস হয়ে গেছে), যার ফলে কাঠামোর ব্যতিক্রম হবে।
ম্যাথিয়াস

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

0

আমি ভেবেছিলাম কাজগুলি বাতিল করুন কিন্তু তা হয় না।

এখানে তারা এটি সম্পর্কে আরটিএফএমিং করছে:

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

এটি বোঝায় না যে থ্রেডটি বাধাপ্রাপ্ত। এটি জাভা জিনিস, অ্যাসিঙ্কটাস জিনিস নয় ""

http://groups.google.com/group/android-developers/browse_thread/thread/dcadb1bc7705f1bb/add136eb4949359d?show_docid=add136eb4949359d


0

অ্যাসিঙ্কটাস্ককে এমন কার্যকলাপ হিসাবে ভাবা আরও ভাল হবে যে কোনও ক্রিয়াকলাপ, প্রসঙ্গ, কনটেক্সট ব্র্যাপার ইত্যাদির সাথে আরও দৃ tight়তার সাথে মিলিত হয় যখন এর সুযোগটি পুরোপুরি বোঝা যায় তখন এটি আরও সুবিধার।

আপনার জীবনকালক্রমে আপনার একটি বাতিল নীতি রয়েছে তা নিশ্চিত করুন যাতে এটি অবশেষে আবর্জনা সংগ্রহ করা যায় এবং আপনার ক্রিয়াকলাপের আর কোনও উল্লেখ রাখে না এবং এটিও আবর্জনা সংগ্রহ করা যেতে পারে।

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

অ্যাসিঙ্কটাস্ক সব খারাপ নয় তবে অবশ্যই প্রচুর যাদু চলছে যা কিছু অপ্রত্যাশিত সমস্যার সৃষ্টি করতে পারে।


-1

"এটির সাথে কাজ করার অভিজ্ঞতা" হিসাবে: এটি সম্ভব করতে প্রক্রিয়া হত্যা সব AsyncTasks সহ, অ্যান্ড্রয়েড কার্যকলাপ স্ট্যাক পুনরায় তৈরি যাতে ব্যবহারকারী কিছু উল্লেখ না হবে।

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