AsyncTask কয়েকবার চালিত করুন


127

আমার ক্রিয়াকলাপে আমি এমন একটি ক্লাস ব্যবহার করি যা অ্যাসিঙ্কটাস্ক থেকে শুরু করে একটি পরামিতি যা সেই অ্যাসিঙ্কটাসকের উদাহরণ of আমি যখন ফোন করি তখন mInstanceOfAT.execute("")সব ঠিক আছে। তবে আমি যখন একটি আপডেট বোতাম টিপুন তখন অ্যাপটি ক্র্যাশ হয় যা আবার অ্যাসিঙ্কটাস্ককে কল করে (যদি নেটওয়ার্ক জব কাজ না করে)। এরপরে একটি ব্যতিক্রম দেখা যায় যা বলে

কার্য সম্পাদন করা যায় না: টাস্কটি ইতিমধ্যে কার্যকর করা হয়েছে (কোনও কাজ কেবল একবার সম্পাদন করা যেতে পারে)

Asyctask এর উদাহরণ হিসাবে আমি বাতিল (সত্য) কল করার চেষ্টা করেছি, তবে এটি কার্যকর হয় না। এখন পর্যন্ত একমাত্র সমাধান এটি অ্যাসিনটাস্কের নতুন উদাহরণ তৈরি করা create এটা কি সঠিক উপায়?

ধন্যবাদ।

উত্তর:


217

AsyncTask উদাহরণগুলি কেবল একবার ব্যবহার করা যেতে পারে।

পরিবর্তে, ঠিক যেমন আপনার টাস্ক কল new MyAsyncTask().execute("");

AsyncTask API ডক্স থেকে:

থ্রেডিং বিধি

এই শ্রেণীর যথাযথভাবে কাজ করার জন্য কয়েকটি থ্রেডিং বিধি অনুসরণ করা আবশ্যক:

  • টাস্ক ইনস্ট্যান্সটি অবশ্যই ইউআই থ্রেডে তৈরি করা উচিত।
  • এক্সিকিউট (প্যারামস ...) অবশ্যই ইউআই থ্রেডে ডাকা হবে।
  • OnPreExecute (), onPostExecute (ফলাফল), doInBackground (প্যারাম ...), onProgressUpdate (অগ্রগতি ...) ম্যানুয়ালি কল করবেন না।
  • টাস্কটি কেবল একবার কার্যকর করা যেতে পারে (দ্বিতীয় কার্যকর করার চেষ্টা করা হলে ব্যতিক্রম ছুঁড়ে দেওয়া হবে))

2
আমি যা বলেছি তা করেছি, এটাই কি একমাত্র সম্ভাবনা? কারণ আমি কোনও নতুন অবজেক্ট তৈরির পরিবর্তে স্মৃতি সংরক্ষণ করতে চাই।
ডায়ারম্যান


@ স্টিভেনট্রাইস: যদি আমি সার্ভারে ডেটা প্রেরণ করার জন্য প্রতিটি এক্স সেকেন্ডে নতুন টাস্ক () দিয়ে এক্সিকিউট (প্যারাম) দিয়ে টাস্কের একটি উদাহরণ তৈরি করি, এক্সিকিউট কার্যকর হয়ে গেলে কীভাবে আবর্জনা সংগ্রহকারী মেমরি ছেড়ে দিতে পারে?
Ant4res

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

28

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

আপনার এক্সিকিউটেবল কোডটি ডোইনব্যাকগ্রাউন্ডের () এর মধ্যে একটি লুপের মধ্যে রাখুন এবং প্রতিটি সম্পাদনকে ট্রিগার করতে একটি যুগল লক ব্যবহার করুন। আপনি প্রকাশপ্রগ্রহ () / অনপ্রস্রেস আপডেট () ব্যবহার করে ফলাফল পুনরুদ্ধার করতে পারেন ।

উদাহরণ:

class GetDataFromServerTask extends AsyncTask<Input, Result, Void> {

    private final ReentrantLock lock = new ReentrantLock();
    private final Condition tryAgain = lock.newCondition();
    private volatile boolean finished = false;

    @Override
    protected Void doInBackground(Input... params) {

        lock.lockInterruptibly();

        do { 
            // This is the bulk of our task, request the data, and put in "result"
            Result result = ....

            // Return it to the activity thread using publishProgress()
            publishProgress(result);

            // At the end, we acquire a lock that will delay
            // the next execution until runAgain() is called..
            tryAgain.await();

        } while(!finished);

        lock.unlock();
    }

    @Override
    protected void onProgressUpdate(Result... result) 
    {
        // Treat this like onPostExecute(), do something with result

        // This is an example...
        if (result != whatWeWant && userWantsToTryAgain()) {
            runAgain();
        }
    }

    public void runAgain() {
        // Call this to request data from the server again
        tryAgain.signal();
    }

    public void terminateTask() {
        // The task will only finish when we call this method
        finished = true;
        lock.unlock();
    }

    @Override
    protected void onCancelled() {
        // Make sure we clean up if the task is killed
        terminateTask();
    }
}

অবশ্যই এটি ASyncTask এর traditionalতিহ্যগত ব্যবহারের চেয়ে কিছুটা জটিল এবং আপনি প্রকৃত অগ্রগতি প্রতিবেদনের জন্য পাবলিশপ্রোগ্রেস () ব্যবহারটি ছেড়ে দেন । তবে যদি মেমোরিটি আপনার উদ্বেগের বিষয় হয়ে থাকে, তবে এই পদ্ধতিটি রানটাইমের সময় কেবলমাত্র একটি এ্যাসএনটাস্ক রয়ে গেছে the


তবে মূল কথাটি হ'ল আমি চলমান চলাকালীন অ্যাসিনটাস্কটিকে পুনরায় শুরু করতে চাই না, তবে এটির কারণ হিসাবে এটি শেষ হয়ে গেছে এবং ডাটাটি যেমনটি করা উচিত ঠিক তেমন গ্রহণ করতে পারে নি, তারপরে আবার কল করুন।
ডায়ারম্যান

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

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

আমি কী বলতে চাইছি তা বর্ণনা করতে আমি কয়েকটি উদাহরণ কোড যুক্ত করেছি। ফলাফলের সাথে আপনি খুশি হয়ে এ্যাসিনটাস্ক কেবল তখনই শেষ করবে এবং "টার্মিনেট টাস্ক ()" কল করবে।
seanhodges

1
আপনি পেতে পারেন IllegalMonitorStateExceptionrunAgain(ডাকা onProgressUpdate) এই উত্তর দেখুন: stackoverflow.com/a/42646476/2711811 । এটি পরামর্শ দেয় (এবং আমার জন্য কাজ করেছিল) যে signal()প্রয়োজনগুলি ঘিরে রাখা উচিত lock/ / unlockpublishProgressকল করার সময়টির সাথে এটি থাকতে পারে onProgressUpdate
অ্যান্ডি

2

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

সুতরাং পোস্টপ্যাক্সেকুটে () এ আমি যা করেছি তা হ'ল:

instance = null;

এই বিষয়টি মাথায় রেখে আমি স্থিতিশীল getInstance পদ্ধতিটি পরীক্ষা করে দেখি যে আমার উদাহরণটি বাতিল নয়, অন্যথায় আমি এটি তৈরি করেছি:

if (instance == null){
    instance = new Task();
}
return instance;

পোস্টএক্সেকুটে পদ্ধতিটি দৃষ্টান্তটি খালি করে পুনরায় তৈরি করবে। অবশ্যই এটি ক্লাসের বাইরে করা যেতে পারে।


1

আমি আমার ঘোরানোর কাজগুলি স্থির করে তুলেছি, যা ঘূর্ণন পরিবর্তনে ইউআই থ্রেডগুলিতে সংযুক্ত করতে, বিচ্ছিন্ন করতে এবং পুনরায় যুক্ত করতে সহায়তা করেছিল। তবে আপনার প্রশ্নে ফিরে যাওয়ার জন্য, আমি কী করব তা হল धागाটি চলছে কিনা তা দেখার জন্য একটি পতাকা তৈরি করা। আপনি যখন থ্রেডটি পুনঃসূচনা করতে চান তখন আমি পরীক্ষা করে দেখি যে এটি ঘূর্ণন কাজটি চালিত হচ্ছে যদি আমি কোনও সতর্কতা টস্ট করি। যদি এটি না হয় তবে আমি এটিকে শূন্য করে তুলি এবং তারপরে একটি নতুন তৈরি করি যা আপনি যে ত্রুটিটি দেখছেন তার চারপাশে কাজ করবে। তদুপরি, সফল সমাপ্তির পরে আমি সম্পূর্ণ ঘূর্ণন সচেতন কার্যটি বাতিল করি যাতে এটি আবার যেতে প্রস্তুত।


0

হ্যাঁ এটি সত্য, ডক বলেছেন যে কেবলমাত্র একটি অ্যাসিনটস্ককে কার্যকর করা যায়।

প্রতিবার এটি ব্যবহার করার দরকার রয়েছে আপনাকে উদাহরণস্বরূপ:

// Any time if you need to call her
final FirmwareDownload fDownload = new FirmwareDownload();
fDownload.execute("your parameter");

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