সংজ্ঞায়িত অন্তরগুলিতে অ্যান্ড্রয়েডে কীভাবে রান্নেবল থ্রেড চালানো যায়?


351

আমি অ্যান্ড্রয়েড এমুলেটর স্ক্রিনে সংজ্ঞায়িত বিরতিতে কিছু পাঠ্য প্রদর্শন করার জন্য একটি অ্যাপ্লিকেশন তৈরি করেছি। আমি Handlerক্লাস ব্যবহার করছি । আমার কোড থেকে একটি স্নিপেট এখানে দেওয়া হয়েছে:

handler = new Handler();
Runnable r = new Runnable() {
    public void run() {
        tv.append("Hello World");               
    }
};
handler.postDelayed(r, 1000);

আমি যখন এই অ্যাপ্লিকেশনটি চালনা করি তখন পাঠ্যটি একবারে প্রদর্শিত হয়। কেন?


109

2
হাহা একই এখানে এখানে সাথী
NoXSaeeD

1
ল্যাম্বডাস এখন বেশিরভাগ সময় যাবার উপায়;)
জেরুস

@ অ্যাড্রিয়ানসিকারু: একই
সোভানদারা এলইএনজি

উত্তর:


534

আপনার উদাহরণের সহজ সমাধান হ'ল:

handler = new Handler();

final Runnable r = new Runnable() {
    public void run() {
        tv.append("Hello World");
        handler.postDelayed(this, 1000);
    }
};

handler.postDelayed(r, 1000);

অথবা আমরা উদাহরণস্বরূপ (মূল রানার সহ) সাধারণ থ্রেড ব্যবহার করতে পারি:

Thread thread = new Thread() {
    @Override
    public void run() {
        try {
            while(true) {
                sleep(1000);
                handler.post(this);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};

thread.start();

আপনি আপনার চলমান বস্তুটিকে ঠিক একটি আদেশ হিসাবে বিবেচনা করতে পারেন যা মৃত্যুর জন্য বার্তা কাতারে প্রেরণ করা যেতে পারে এবং হ্যান্ডলার কেবল সেই আদেশটি প্রেরণের জন্য ব্যবহৃত সহায়ক সাহায্যকারী হিসাবে বিবেচনা করতে পারে।

আরও বিশদ এখানে http://developer.android.com/references/android/os/Handler.html


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

11
আপনি বুলিয়ান ভেরিয়েবল _স্টপ সংজ্ঞায়িত করতে পারেন এবং আপনি থামাতে চাইলে এটি 'সত্য' সেট করতে পারেন। এবং 'সত্য (সত্য)' 'তে' ('(থামানো)' এর মধ্যে 'বা' প্রথম নমুনা ব্যবহৃত হলে কেবল 'যদি (! _ স্টপ) হ্যান্ডেল.পোস্টডিলেড (এটি, 1000)' তে পরিবর্তন করুন।
alex2k8

আমি যদি বার্তাটি পুনরায় চালু করতে চাই তবে কী হবে?
সোনহজা

এবং যদি আমার একের পর এক 8 টি পৃথক চিত্রদর্শন দৃশ্যমান সেট করতে রান্নেবলের প্রয়োজন হয়, তবে সেগুলি সমস্ত একইভাবে অদৃশ্য করে সেট করুন এবং (একটি "ঝলকানো" অ্যানিমেশন তৈরি করতে), আমি কীভাবে এটি করতে পারি?
Droidman 13

1
আপনি যদি নিশ্চিত হতে চান যে হ্যান্ডলারটি মূল থ্রেডের সাথে সংযুক্ত থাকবে, আপনার এটির মতো এটি শুরু করা উচিত: হ্যান্ডলার = নতুন হ্যান্ডলার (লুপার.সেটমাইনলুপার ());
ইয়ার কুকিলকা

47
new Handler().postDelayed(new Runnable() {
    public void run() {
        // do something...              
    }
}, 100);

2
আপনি যদি নিশ্চিত হতে চান যে হ্যান্ডলারটি মূল থ্রেডের সাথে সংযুক্ত থাকবে, আপনার এটির মতো এটি শুরু করা উচিত: নতুন হ্যান্ডলার (লুপার.সেটমাইনলুপার ());
ইয়ার কুকিল্কা

1
এই সমাধানটি কি মূল পোস্টের সমতুল্য নয়? এটি কেবল 100 মিলিসেকেন্ডের পরে একবার রান্নেবল চালিত হবে।
ট্রোনম্যান

@ ইয়ারকুকিয়েলকা উত্তরটি সমাধান! আপনাকে মেইনলুপার সংযুক্ত করতে হবে। এমন জীবন রক্ষাকারী!
Houssem Chlegou

40

আমার মনে হয় আপডেটের জন্য প্রতিটি সেকেন্ডের জন্য অ্যালেক্স 2 কে 8 এর প্রথম সমাধানটি উন্নত করতে পারে

1.আরজিনাল কোড:

public void run() {
    tv.append("Hello World");
    handler.postDelayed(this, 1000);
}

2.Analysis

  • উপরের ব্যয়টিতে, tv.append("Hello Word")মূল্য টি মিলিসেকেন্ডগুলি ধরে রাখুন , প্রদর্শনের পরে 500 বার বিলম্বিত সময় হয় 500 * টি মিলিসেকেন্ড
  • দীর্ঘ সময় চালানোর সময় এটি বিলম্ব বাড়বে

3. সমাধান

দেরি এড়াতে কেবল পোস্টডেলেড () এর ক্রম পরিবর্তন করুন:

public void run() {
    handler.postDelayed(this, 1000);
    tv.append("Hello World");
}

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

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

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

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

27

পুনরাবৃত্তি টাস্কের জন্য আপনি ব্যবহার করতে পারেন

new Timer().scheduleAtFixedRate(task, runAfterADelayForFirstTime, repeaingTimeInterval);

এটি পছন্দ করুন

new Timer().scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {

            }
        },500,1000);

উপরের কোডটি প্রথমবারের পরে অর্ধ সেকেন্ড (500) পরে চলবে এবং প্রতিটি সেকেন্ডের পরে নিজেকে পুনরাবৃত্তি করবে (1000)

কোথায়

টাস্ক হচ্ছে কার্যকর করার পদ্ধতি

প্রাথমিক মৃত্যুর সময় পরে

( বিরতি সম্পাদন পুনরায় জন্য সময়)

দ্বিতীয়ত

এবং আপনি কাউন্টডাউনটাইমারও ব্যবহার করতে পারেন যদি আপনি একটি টাস্ক সংখ্যার সময় কার্যকর করতে চান।

    new CountDownTimer(40000, 1000) { //40000 milli seconds is total time, 1000 milli seconds is time interval

     public void onTick(long millisUntilFinished) {
      }
      public void onFinish() {
     }
    }.start();

//Above codes run 40 times after each second

এবং আপনি এটি রানওয়েবল দিয়েও করতে পারেন। একটি চলমান পদ্ধতি তৈরি করুন

Runnable runnable = new Runnable()
    {
        @Override
        public void run()
        {

        }
    };

এবং এই উভয় উপায়ে এটি কল

new Handler().postDelayed(runnable, 500 );//where 500 is delayMillis  // to work on mainThread

অথবা

new Thread(runnable).start();//to work in Background 

# 3 বিকল্পের জন্য আমি কীভাবে বিরতি / পুনরায় শুরু করতে পারি এবং স্থায়ীভাবে বন্ধ করতে পারি?
Si8

হ্যান্ডলারের মতো হ্যান্ডলারের একটি উদাহরণ তৈরি করুন হ্যান্ডলারের মতো = নতুন হ্যান্ডলারের () এবং এটি হ্যান্ডেলারের মতো সরান rem
জার ই আহমর

24

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

myTimer = new Timer();
myTimer.schedule(new TimerTask() {          
@Override
public void run() {
    // If you want to modify a view in your Activity
    MyActivity.this.runOnUiThread(new Runnable()
        public void run(){
            tv.append("Hello World");
        });
    }
}, 1000, 1000); // initial delay 1 second, interval 1 second

ব্যবহার Timerকয়েক সুফল রয়েছে:

  • প্রাথমিক বিলম্ব এবং অন্তর সহজেই scheduleফাংশন আর্গুমেন্টে নির্দিষ্ট করা যেতে পারে
  • টাইমরটি কেবল কল করে থামানো যেতে পারে myTimer.cancel()
  • আপনি যদি কেবল একটি থ্রেড চলমান রাখতে চান তবে একটি নতুন সময় নির্ধারণের myTimer.cancel() আগে কল করতে ভুলবেন না (যদি আমার টাইমারটি নাল না থাকে)

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

1
এর অর্থ কি যখন কোনও অ্যাপ্লিকেশনটিকে ব্যাকগ্রাউন্ডে রাখা হয় তখন কোনও হ্যান্ডলার থামিয়ে দেওয়া হবে? এবং যখন এটি ফোকাস ফিরে পেয়েছে তখন এটি চালিয়ে যাবে (কমবেশি) যেন কিছুই ঘটেনি?
অ্যান্ড্রু গ্যাল্যাশ

17
Handler handler=new Handler();
Runnable r = new Runnable(){
    public void run() {
        tv.append("Hello World");                       
        handler.postDelayed(r, 1000);
    }
}; 
handler.post(r);

5
এটি একটি ত্রুটি দেওয়া উচিত। আপনার দ্বিতীয় লাইনে আপনি ভেরিয়েবল কল করছেন rযা এখনও সংজ্ঞায়িত is
সিওল

আপনি যদি নিশ্চিত হতে চান যে হ্যান্ডলারটি মূল থ্রেডের সাথে সংযুক্ত থাকবে, আপনার এটির মতো এটি শুরু করা উচিত: হ্যান্ডলার = নতুন হ্যান্ডলার (লুপার.সেটমাইনলুপার ());
ইয়ার কুকিল্কা

শুধু পুনরাবৃত্তি উত্তর!
হামিদ

আমি কীভাবে ইমেজভিউ ক্লিকের সাথে রান রানযোগ্যটিকে বিরতি / পুনঃসূচনা করতে পারি?
Si8

4

যদি আমি হ্যান্ডেলআরপোস্ট () পদ্ধতির ডকুমেন্টেশনটি সঠিকভাবে বুঝতে পারি:

রান্নেবল আর কে বার্তার কাতারে যুক্ত করার কারণ দেয়। এই হ্যান্ডলারটি যে থ্রেডটিতে সংযুক্ত রয়েছে তাতে রান্নেবল চালানো হবে।

সুতরাং @ অ্যালেক্স 2 কে 8 সরবরাহিত উদাহরণগুলি সঠিকভাবে কাজ করা সত্ত্বেও এক নয়। ক্ষেত্রে যেখানে Handler.post()ব্যবহৃত হয়, কোনও নতুন থ্রেড তৈরি হয় না । আপনি কেবল ইডিটি দ্বারা সম্পাদিত হতে Runnableথ্রেডে পোস্ট করুন । এর পরে, ইডিটি কেবল কার্যকর করে , অন্য কিছুই না।HandlerRunnable.run()

মনে রাখবেন: Runnable != Thread


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

এটি করার আরও ভাল উপায় হ'ল অ্যালেক্স 2 কে 8 এর উত্তরের ভিত্তিতে সাধারণ থ্রেড ব্যবহার করে?
কমপ্যাক LE2202x

4

Kotlin

private lateinit var runnable: Runnable
override fun onCreate(savedInstanceState: Bundle?) {
    val handler = Handler()
    runnable = Runnable {
        // do your work
        handler.postDelayed(runnable, 2000)
    }
    handler.postDelayed(runnable, 2000)
}

জাভা

Runnable runnable;
Handler handler;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    handler = new Handler();
    runnable = new Runnable() {
        @Override
        public void run() {
            // do your work
            handler.postDelayed(this, 1000);
        }
    };
    handler.postDelayed(runnable, 1000);
}

1

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

উদ্ধৃতাংশ:

try {    
    cnt++; scnt++;
    now=System.currentTimeMillis();
    r=rand.nextInt(6); r++;    
    loc=lm.getLastKnownLocation(best);    

    if(loc!=null) { 
        lat=loc.getLatitude();
        lng=loc.getLongitude(); 
    }    

    Thread.sleep(100); 
    handler.sendMessage(handler.obtainMessage());
} catch (InterruptedException e) {   
    Toast.makeText(this, "Error="+e.toString(), Toast.LENGTH_LONG).show();
}

কোড দেখতে এখানে দেখুন:

মূল ক্রিয়াকলাপের ব্যবহারকারী ইন্টারফেস থ্রেডের পাশাপাশি জিপিএসের অবস্থান এবং বর্তমান সময়ের জন্য চলমান থ্রেড উদাহরণ


1
ইঙ্গিত: আপনি যদি নিজের উত্তরটি দরকারী করতে চান - কীভাবে এখানে ইনপুট ফর্ম্যাট করবেন তা শিখুন। সেই পূর্বরূপ উইন্ডো একটি কারণে বিদ্যমান।
ঘোস্টটিক

0

এখন কোটলিনে আপনি এভাবে থ্রেড চালাতে পারেন:

class SimpleRunnable: Runnable {
    public override fun run() {
        println("${Thread.currentThread()} has run.")
    }
}
fun main(args: Array<String>) {
    val thread = SimpleThread()
    thread.start() // Will output: Thread[Thread-0,5,main] has run.
    val runnable = SimpleRunnable()
    val thread1 = Thread(runnable)
    thread1.start() // Will output: Thread[Thread-1,5,main] has run
}

0

কোটলিন সহ কর্টিনস

কোটলিনে, কর্টাইন ব্যবহার করে আপনি নিম্নলিখিতটি করতে পারেন:

CoroutineScope(Dispatchers.Main).launch { // Main, because UI is changed
    ticker(delayMillis = 1000, initialDelayMillis = 1000).consumeEach {
        tv.append("Hello World")
    }
}

এখানে চেষ্টা করে দেখুন !

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