অ্যান্ড্রয়েডে পুনরাবৃত্তি টাস্কের সময় নির্ধারণ


122

আমি এমন একটি অ্যাপ্লিকেশন ডিজাইন করছি যা যতক্ষণ না অ্যাপ্লিকেশনটি পূর্বের পৃষ্ঠায় থাকে ততক্ষণ কোনও ডেডিকেটেড সার্ভারে উপস্থিতি প্রেরণের বারবার কাজ হয়।

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

কোনও সার্ভার কল শিডিয়ুল করার সেরা উপায় কী?

আমি যে বিকল্পগুলি দেখেছি সেগুলি হ'ল:

  1. টাইমার

  2. নির্ধারিত থ্রেডপুলএক্সেকিউটার

  3. সেবা

  4. অ্যালার্ম ম্যানেজারের সাথে ব্রডকাস্টআরসিভার ।

তোমার মতামত কি?

সম্পাদনা: আমার
যে কারণটি প্রয়োজন তা হ'ল চ্যাট ভিত্তিক অ্যাপ্লিকেশন যা সমস্ত ব্যবহারকারীর ক্রিয়াগুলি দূরবর্তী সার্ভারে প্রেরণ করে।
অর্থাত্ ব্যবহারকারী কোনও বার্তা টাইপ করছেন, ব্যবহারকারী একটি বার্তা পড়ছেন, ব্যবহারকারী অনলাইন, ব্যবহারকারী অফলাইন etc.

এর অর্থ হ'ল প্রতি বিরতিতে একবার, আমি যা করছি তা সার্ভারটি প্রেরণ করা দরকার, যেহেতু আমি অন্য লোকের সাথে চ্যাট রুম খুলি, তাদের আমি জানতে চাই যে তারা কী করছে।

হোয়াটসঅ্যাপ বার্তার মতামত প্রক্রিয়া মত: বার্তা বিতরণ করা লাগে

সম্পাদনা # 2: অ্যান্ড্রয়েড প্রশিক্ষণের গুরুত্বপূর্ণ অংশে পড়া ব্যাটারি প্রবাহের সমস্যাগুলি রোধ করার জন্য,
পুনরাবৃত্ত কাজগুলি প্রায়শই সর্বদা JobSchedulerএপিআই (বা FirebaseJobDispatcherনিম্ন APIs) এর মাধ্যমে নির্ধারিত করা উচিত

সম্পাদনা # 3: ফায়ারবেস জবডিসপ্যাচারকে ওয়ার্কম্যানেজার
দ্বারা অবচিত ও প্রতিস্থাপন করা হয়েছে , যা জোবশেডুলারের বৈশিষ্ট্যগুলিও অন্তর্ভুক্ত করে।


2
অ্যালার্মম্যানেজারের সাথে ব্রোকেস্টআরসিভারটি ব্যবহারের জন্য বেশ সোজা-ফরোয়ার্ড। উপরোক্ত বিকল্পগুলির মধ্যে কেবলমাত্র আমি চেষ্টা করেছি।

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

সংক্ষিপ্তভাবে চলমান জীবনচক্রের জন্য, যেমন বর্তমানে পূর্বে অবস্থিত একটি ক্রিয়াকলাপে প্রতি 30 সেকেন্ডে কিছু কাজ সম্পাদন করুন, শিডিউডথ্রেডপুলঅ্যাক্সিকিউটর (বা টাইমার) আরও দক্ষ use দীর্ঘ চলমান জীবনচক্রের জন্য, অর্থাত্ একটি পটভূমি পরিষেবাতে প্রতি 1 ঘন্টা অন্তত কিছু কাজ সম্পাদন করুন, অ্যালার্ম ম্যানেজারটি আরও নির্ভরযোগ্যতা দেয়।
ইয়র্কউ

এমনকি কেন আপনার প্রেরণের সময়সূচী প্রয়োজন? আপনার অ্যাপ্লিকেশন বর্ণনা থেকে কেন আপনি কেবল এটি রিয়েল-টাইমে প্রেরণ করেন না?
আইটেক

কারণ ব্যবহারকারী ধরে নিয়েছে যে আপনি একটি সময়সীমা ব্যবহার করে অনলাইনে রয়েছেন। অর্থ, যদি আমি গত X পরিমাণে "উপস্থিতি" বা "টাইপিং" বার্তাটি না পেয়ে থাকি তবে আমি স্বয়ংক্রিয়ভাবে ধরে নিই যে আপনি এটি করছেন না
Thepoosh

উত্তর:


164

আমি নিশ্চিত নই তবে আমার জ্ঞান অনুসারে আমি আমার মতামত শেয়ার করছি। আমি ভুল হলে আমি সর্বদা সেরা উত্তর গ্রহণ করি।

অ্যালার্ম ম্যানেজার

অ্যালার্ম ম্যানেজারটি যতক্ষণ না অ্যালার্ম রিসিভারের onReceive()পদ্ধতিটি চালিত হয় ততক্ষণ একটি সিপিইউ ওয়েগ লক ধরে থাকে । এটি গ্যারান্টি দেয় যে আপনি ব্রডকাস্ট পরিচালনা পরিচালনা শেষ না করা পর্যন্ত ফোনটি ঘুমাবে না। একবার onReceive()ফিরে আসার পরে অ্যালার্ম ম্যানেজার এই জাগ্রত লকটি প্রকাশ করে। এর অর্থ হল যে আপনার onReceive()পদ্ধতিটি শেষ হওয়ার সাথে সাথে ফোনটি কিছু ক্ষেত্রে ঘুমাবে sleep যদি আপনার অ্যালার্মের রিসিভারটি কল করা হয় Context.startService(), তবে অনুরোধ করা পরিষেবাটি চালু হওয়ার আগেই ফোনটি ঘুমোতে পারে। এটি প্রতিরোধ করতে, আপনার BroadcastReceiverএবং Serviceতার জন্য পরিষেবাটি উপলব্ধ না হওয়া পর্যন্ত ফোনটি চলতে থাকবে তা নিশ্চিত করার জন্য একটি পৃথক ওয়েক লক নীতি বাস্তবায়ন করতে হবে।

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

সময় নির্ণায়ক

timer = new Timer();

    timer.scheduleAtFixedRate(new TimerTask() {

        synchronized public void run() {

            \\ here your todo;
            }

        }}, TimeUnit.MINUTES.toMillis(1), TimeUnit.MINUTES.toMillis(1));

Timerকিছু ত্রুটি আছে যা দ্বারা সমাধান করা হয় ScheduledThreadPoolExecutor। সুতরাং এটি সেরা পছন্দ নয়

নির্ধারিত থ্রেডপুলএক্সেকিউটার

আপনি ব্যাকগ্রাউন্ড থ্রেডে নিয়মিত বিরতিতে কোনও ক্রিয়াকলাপ নির্ধারণ করতে java.util.Timerবা ScheduledThreadPoolExecutor(পছন্দসই) ব্যবহার করতে পারেন ।

পরেরটি ব্যবহার করে একটি নমুনা এখানে দেওয়া হল:

ScheduledExecutorService scheduler =
    Executors.newSingleThreadScheduledExecutor();

scheduler.scheduleAtFixedRate
      (new Runnable() {
         public void run() {
            // call service
         }
      }, 0, 10, TimeUnit.MINUTES);

তাই আমি পছন্দ ScheduledExecutorService

তবে আপনার অ্যাপ্লিকেশন চলমান চলাকালীন আপডেটগুলি যদি ঘটে থাকে তবে সে সম্পর্কেও ভাবুন, আপনি Timerঅন্যান্য উত্তরগুলিতে বা নতুনটি হিসাবে পরামর্শ মতো একটি ব্যবহার করতে পারেন ScheduledThreadPoolExecutor। আপনার অ্যাপ্লিকেশনটি চলমান না থাকলেও যদি আপডেট হয় তবে আপনার সাথে থাকা উচিত AlarmManager

অ্যালার্ম ম্যানেজারটি এমন ক্ষেত্রে তৈরি হয় যেখানে আপনি আপনার অ্যাপ্লিকেশন কোডটি একটি নির্দিষ্ট সময়ে চালাতে চান, এমনকি আপনার অ্যাপ্লিকেশন বর্তমানে চলমান না থাকলেও।

নোট নিন যে আপনি যদি আপডেট করার পরিকল্পনা যখন আপনার আবেদন বন্ধ পরিণত হয়, প্রতি দশ মিনিট একবার বেশ ঘন, এবং এইভাবে সম্ভবত একটি বিট খুব ক্ষমতা ব্যয়কারী।


আমি একটি নির্দিষ্ট সময় অন্তর অন্তর কাজের জন্য এই পদ্ধতি চেষ্টা করছি, কিন্তু এটা কাজ বলে মনে হচ্ছে না stackoverflow.com/questions/27872016/...
dowjones123

সাধারণ জিনিসগুলির জন্য - প্রতি এন-সেকেন্ডে স্থিতি পরীক্ষা করা-টাইমার করণীয়।
ইগোরগানাপলস্কি

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

30

সময় নির্ণায়ক

জাভাডোকগুলিতে উল্লিখিত হিসাবে আপনি একটি নির্ধারিত থ্রেডপুলঅ্যাক্সিকিউটর ব্যবহার করা ভাল।

ScheduledThreadPoolExecutor

যখন আপনার ব্যবহারের ক্ষেত্রে একাধিক কর্মী থ্রেড প্রয়োজন হয় এবং ঘুমের ব্যবধানটি ছোট হয় তখন এই শ্রেণিটি ব্যবহার করুন। কত ছোট? ঠিক আছে, আমি প্রায় 15 মিনিট বলতে চাই। এই AlarmManagerসময়সূচির ব্যবধানগুলি শুরু হয় এবং এটি মনে হয় যে ছোট ঘুমের ব্যবধানের জন্য এই শ্রেণিটি ব্যবহার করা যেতে পারে। শেষ বিবৃতিটি ব্যাক করার জন্য আমার কাছে ডেটা নেই। এটি একটি কুঁচক

সেবা

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

অ্যালার্ম ম্যানেজারের সাথে ব্রডকাস্টআরসিভার

দীর্ঘ ঘুমের ব্যবধানে (> 15 মিনিট), এটি যাওয়ার উপায়। AlarmManagerইতিমধ্যে ধ্রুবক রয়েছে ( AlarmManager.INTERVAL_DAY) পরামর্শ দেয় যে এটি প্রাথমিকভাবে নির্ধারিত হওয়ার পরে বেশ কয়েক দিন পরে কাজগুলি ট্রিগার করতে পারে। এটি আপনার কোড চালানোর জন্য সিপিইউ জাগাতে পারে।

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


1
তাই যদি আমি অ্যাপটি ব্যবহার করতে চাই এবং প্রতি আধা ঘন্টা পরে আমি ব্যাক-আপ করতে চাই। তবে অ্যাপটি ব্যবহার না করা অবস্থায় আমি ব্যাক আপ নিতে চাই না (এটি সামগ্রিক অপচয় হবে)। অ্যালার্ম ম্যানেজার পুনরায় বুট না হওয়া পর্যন্ত ক্রমাগত ক্রিয়াটির পুনরাবৃত্তি করবে (এটি আমি শুনেছি কমপক্ষে)। আপনি কি সুপারিশ করতেন? শিডিউলথ্রেডপুলএক্সেক্টর বা অ্যালার্ম ম্যানেজার?
hasdrubal

13

আমি বুঝতে পারি এটি একটি পুরানো প্রশ্ন এবং এর উত্তর দেওয়া হয়েছে তবে এটি কাউকে সহায়তা করতে পারে। আপনারactivity

private ScheduledExecutorService scheduleTaskExecutor;

ভিতরে onCreate

  scheduleTaskExecutor = Executors.newScheduledThreadPool(5);

    //Schedule a task to run every 5 seconds (or however long you want)
    scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            // Do stuff here!

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // Do stuff to update UI here!
                    Toast.makeText(MainActivity.this, "Its been 5 seconds", Toast.LENGTH_SHORT).show();
                }
            });

        }
    }, 0, 5, TimeUnit.SECONDS); // or .MINUTES, .HOURS etc.

2

শিডিউল পুনরাবৃত্তি আলার্মের উদ্ধৃতি - ট্রেড-অফস ডক্সটি বুঝুন :

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

সুতরাং, এর ভিত্তিতে, সার্ভার কলটি নির্ধারণের সেরা উপায় হ'ল গুগল ক্লাউড মেসেজিং (জিসিএম) সিঙ্ক অ্যাডাপ্টারের সাথে একত্রে ।


1

আমি টাইম টাস্কে তৈরি করেছি যাতে কাস্টম টাইম টাস্ক রান () পদ্ধতিতে ব্যবহারকারী কোন টাস্কটি পুনরাবৃত্তি করতে চায়। এটি সফলভাবে পুনরায় শুরু হয়।

 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Timer;
 import java.util.TimerTask;

 import android.os.Bundle;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
 import android.widget.CheckBox;
 import android.widget.TextView;
 import android.app.Activity;
 import android.content.Intent;

 public class MainActivity extends Activity {

     CheckBox optSingleShot;
     Button btnStart, btnCancel;
     TextView textCounter;

     Timer timer;
     MyTimerTask myTimerTask;

     int tobeShown = 0  ;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    optSingleShot = (CheckBox)findViewById(R.id.singleshot);
    btnStart = (Button)findViewById(R.id.start);
    btnCancel = (Button)findViewById(R.id.cancel);
    textCounter = (TextView)findViewById(R.id.counter);
    tobeShown = 1;

    if(timer != null){
        timer.cancel();
    }

    //re-schedule timer here
    //otherwise, IllegalStateException of
    //"TimerTask is scheduled already" 
    //will be thrown
    timer = new Timer();
    myTimerTask = new MyTimerTask();

    if(optSingleShot.isChecked()){
        //singleshot delay 1000 ms
        timer.schedule(myTimerTask, 1000);
    }else{
        //delay 1000ms, repeat in 5000ms
        timer.schedule(myTimerTask, 1000, 1000);
    }

    btnStart.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View arg0) {


            Intent i = new Intent(MainActivity.this, ActivityB.class);
            startActivity(i);

            /*if(timer != null){
                timer.cancel();
            }

            //re-schedule timer here
            //otherwise, IllegalStateException of
            //"TimerTask is scheduled already" 
            //will be thrown
            timer = new Timer();
            myTimerTask = new MyTimerTask();

            if(optSingleShot.isChecked()){
                //singleshot delay 1000 ms
                timer.schedule(myTimerTask, 1000);
            }else{
                //delay 1000ms, repeat in 5000ms
                timer.schedule(myTimerTask, 1000, 1000);
            }*/
        }});

    btnCancel.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {
            if (timer!=null){
                timer.cancel();
                timer = null;
            }
        }
    });

}

@Override
protected void onResume() {
    super.onResume();

    if(timer != null){
        timer.cancel();
    }

    //re-schedule timer here
    //otherwise, IllegalStateException of
    //"TimerTask is scheduled already" 
    //will be thrown
    timer = new Timer();
    myTimerTask = new MyTimerTask();

    if(optSingleShot.isChecked()){
        //singleshot delay 1000 ms
        timer.schedule(myTimerTask, 1000);
    }else{
        //delay 1000ms, repeat in 5000ms
        timer.schedule(myTimerTask, 1000, 1000);
    }
}


@Override
protected void onPause() {
    super.onPause();

    if (timer!=null){
        timer.cancel();
        timer = null;
    }

}

@Override
protected void onStop() {
    super.onStop();

    if (timer!=null){
        timer.cancel();
        timer = null;
    }

}

class MyTimerTask extends TimerTask {

    @Override
    public void run() {

        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat simpleDateFormat = 
                new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
        final String strDate = simpleDateFormat.format(calendar.getTime());

        runOnUiThread(new Runnable(){

            @Override
            public void run() {
                textCounter.setText(strDate);
            }});
    }
}

}

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