লুপারের উদ্দেশ্য কী এবং এটি কীভাবে ব্যবহার করা যায়?


454

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


7
আমি সবেমাত্র লুপার এবং এটি সাফারি বুকস অনলাইনে ব্যবহারের একটি অসাধারণ এবং পরিস্কার ব্যাখ্যা পেয়েছি। দুর্ভাগ্যক্রমে, আমি সীমিত সময়ের জন্য অবাধে অ্যাক্সেসের সন্দেহ করি। সাফারিবুকসনলাইন.লাইবারি
জো ল্যাপ

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

1
আমি এই নিবন্ধটি দরকারী বলে খুঁজে পেয়েছি: codetheory.in/…
হারমান

উত্তর:


396

লুপার কী?

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

আমরা কোথায় লুপার ক্লাস ব্যবহার করতে পারি?

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

কিভাবে এটা কাজ করে?

নেই prepare()Looper প্রস্তুত করতে পদ্ধতি। তারপরে আপনি loop()বর্তমান থ্রেডে একটি বার্তা লুপ তৈরি করতে পদ্ধতিটি ব্যবহার করতে পারেন এবং আপনার লুপটি লুপটি ছাড়ার আগ পর্যন্ত আপনার সারিতে থাকা অনুরোধগুলি কার্যকর করতে প্রস্তুত।

এখানে কোডটি যার মাধ্যমে আপনি লুপার প্রস্তুত করতে পারেন।

class LooperThread extends Thread {
      public Handler mHandler;

      @Override
      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              @Override
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }

17
একটি অ্যাসিঙ্কটাস্ক সেই উদ্দেশ্যে ভাল এবং কম জটিল কারণ এটি সমস্ত থ্রেড ম্যানেজিংকে আবদ্ধ করে।
ফার্নান্দো গাল্লেগো

4
রান () এবং হ্যান্ডেলমেজেজ () পদ্ধতির আগে @ ওভাররাইড টিকা থাকতে হবে
অ্যান্ড্রু ম্যাকেনজি

5
ডকুমেন্টেশন ইঙ্গিত দেয় যে আপনাকে অবশ্যই লুপার.কুইট কল করতে হবে। উপরে আপনার কোডে, Looper.loop অনির্দিষ্টকালের জন্য ব্লক হবে।
অ্যান্ড্রয়েডদেভ

2
কিভাবে একটি লুপ ছেড়ে যায়। আমি বোঝাতে চাইছি উপরের কোড উদাহরণে কোথায় Looper.quit () অন্তর্ভুক্ত করবেন?
Seenu69

6
আমি মনে করি হ্যান্ডলারথ্রেড ব্যবহার করা আরও ভাল হবে যা কোনও লুপের সাথে থ্রেডের জন্য সুবিধাজনক শ্রেণি।
নিম্রোদ দয়ান

287

জিইউআই কাঠামোর প্রসঙ্গে লুপারটি কী তা আপনি আরও ভাল করে বুঝতে পারবেন। লুপার 2 টি জিনিস করা হয়।

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

২) লুপার একটি সারি সরবরাহ করে যেখানে কাজগুলি করা হবে এবং জিইউআই কাঠামোর ক্ষেত্রেও এটি প্রয়োজনীয়।

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

public class HelloRunnable implements Runnable {
    public void run() {
        System.out.println("Hello from a thread!");
    }

    public static void main(String args[]) {
        (new Thread(new HelloRunnable())).start();
    }
}

এখন, Android অ্যাপগুলিতে এই সাধারণ নীতিটি প্রয়োগ করি। কোনও অ্যান্ড্রয়েড অ্যাপ স্বাভাবিক থ্রেডে চললে কী হবে? "মেইন" বা "ইউআই" নামে পরিচিত একটি থ্রেড বা যা কিছু আপনার অ্যাপ্লিকেশন শুরু করে এবং সমস্ত ইউআই আঁকেন। সুতরাং, প্রথম পর্দা ব্যবহারকারীদের প্রদর্শিত হয়। এখন কি? মূল থ্রেড কি শেষ? না, এটা করা উচিত নয়। এটি ব্যবহারকারীদের কিছু না করা পর্যন্ত অপেক্ষা করা উচিত, তাই না? তবে কীভাবে আমরা এই আচরণ অর্জন করতে পারি? ঠিক আছে, আমরা চেষ্টা করতে পারি Object.wait()বা এর সাথেThread.sleep()। উদাহরণস্বরূপ, প্রধান থ্রেডটি প্রথম স্ক্রিন প্রদর্শন করার জন্য প্রাথমিক কাজটি শেষ করে এবং ঘুমায়। এটি জাগ্রত হয়, যার অর্থ বাধাগ্রস্ত হয়, যখন করার একটি নতুন কাজ এনে দেওয়া হয়। এখন পর্যন্ত এত ভাল, তবে এই মুহুর্তে আমাদের একাধিক কাজ ধরে রাখতে একটি সারির মতো ডেটা কাঠামো দরকার। কোনও ব্যবহারকারী যখন সিরিয়ালি পর্দা স্পর্শ করে তখন কোনও কেস সম্পর্কে চিন্তা করুন এবং কোনও কাজ শেষ হতে আরও বেশি সময় নেয়। সুতরাং, ফার্স্ট-ইন-ফার্স্ট-আউট পদ্ধতিতে কাজগুলি ধরে রাখতে আমাদের একটি ডেটা কাঠামো থাকা দরকার। এছাড়াও, আপনি কল্পনাও করতে পারেন, আন্তঃ-বিঘ্নিত ব্যবহার করে সর্বদা চলমান ও প্রক্রিয়া-কাজ-কখন-আগত থ্রেড কার্যকর করা সহজ নয় এবং জটিল এবং প্রায়শই অবিশ্বাস্য কোডের দিকে নিয়ে যায়। আমরা বরং এই জাতীয় উদ্দেশ্যে একটি নতুন প্রক্রিয়া তৈরি করতে চাই এবং এটিই লুপার সম্পর্কেLooper বর্গ অফিসিয়াল ডকুমেন্টবলে, "ডিফল্টভাবে থ্রেডগুলির সাথে একটি বার্তা লুপ থাকে না" এবং লুপার একটি ক্লাস "থ্রেডের জন্য বার্তা লুপ চালানোর জন্য ব্যবহৃত হয়"। এর অর্থ কী তা আপনি বুঝতে পারবেন।

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

public final class ActivityThread {
    ...
    public static void main(String[] args) {
        ...
        Looper.prepareMainLooper();
        Looper.loop();
        ...
    }
}

এবং Looper.loop()পদ্ধতিটি অসীমভাবে লুপ করে এবং একটি বার্তা প্রেরণ করে এবং একবারে একটি প্রক্রিয়া করে:

public static void loop() {
    ...
    for (;;) {
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }
        ...
        msg.target.dispatchMessage(msg);
        ...
    }
}

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


26
এটিই কেবলমাত্র উত্তর যা লুপার শ্রেণি কেন ব্যবহৃত হবে সে সম্পর্কে আসলে কিছু ব্যাখ্যা করে। আমি নিশ্চিত নই কেন এটি শীর্ষ উত্তর নয়, তিনটি উচ্চ-রেটযুক্ত উত্তর কিছুই ব্যাখ্যা করে না।
অ্যান্ড্রু কোস্টার

4
@AK। এই কারণেই আমি এই উত্তরটি যুক্ত করেছিলাম এমনকি এটি খুব দেরী বলে মনে হয়েছিল। আমার উত্তর আপনাকে সাহায্য করেছে বলে আমি আনন্দিত! :)
김준호

1
@ হেই-মেন-হোয়াটসআপ হ্যাঁ
김준호

1
এটি পড়ার আগে আমি "লুপার ???" এর মতো ছিলাম এবং এখন "ওহ হ্যাঁ, এটি আলোচনা করা যাক"। ধন্যবাদ মানুষ, দুর্দান্ত উত্তর :)
umerk44

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

75

লুপারটি একক থ্রেডে ক্রমানুসারে কার্য সম্পাদন করার অনুমতি দেয়। এবং হ্যান্ডলার সেই কাজগুলি সংজ্ঞায়িত করে যা আমাদের কার্যকর করতে হবে। এটি একটি সাধারণ দৃশ্য যা আমি এই উদাহরণে তুলে ধরতে চেষ্টা করছি:

class SampleLooper extends Thread {
@Override
public void run() {
  try {
    // preparing a looper on current thread     
    // the current thread is being detected implicitly
    Looper.prepare();

    // now, the handler will automatically bind to the
    // Looper that is attached to the current thread
    // You don't need to specify the Looper explicitly
    handler = new Handler();

    // After the following line the thread will start
    // running the message loop and will not normally
    // exit the loop unless a problem happens or you
    // quit() the looper (see below)
    Looper.loop();
  } catch (Throwable t) {
    Log.e(TAG, "halted due to an error", t);
  } 
}
}

এখন আমরা লুপারের উপর কার্য সম্পাদন করতে টাস্কটি পোস্ট করতে কিছু অন্যান্য থ্রেডে (ইউআই থ্রেড বলে) ব্যবহার করতে পারি।

handler.post(new Runnable()
{
public void run() {
//This will be executed on thread using Looper.
    }
});

ইউআই থ্রেডে আমাদের একটি অন্তর্নিহিত লুপার রয়েছে যা আমাদের ইউআই থ্রেডে বার্তাগুলি পরিচালনা করতে দেয়।


এটি কোনও ইউআই প্রক্রিয়া লক করবে না, এটি কি সত্য?
gumuruh

4
কীভাবে "
চাকরীগুলি

এটি ব্যাখ্যা করে না যে কেন কেউ এই ক্লাসটি ব্যবহার করবে, কেবল কীভাবে।
অ্যান্ড্রু কোস্টার

33

অ্যান্ড্রয়েড Looperসংযুক্ত MessageQueueকরার জন্য একটি মোড়ক Threadএবং এটি সারি প্রক্রিয়াকরণ পরিচালনা করে। এটি অ্যান্ড্রয়েড ডকুমেন্টেশনে খুব ক্রিপ্টিক দেখায় এবং অনেক সময় আমরা মুখোমুখি হতে পারিLooper সম্পর্কিত ইউআই অ্যাক্সেস সমস্যার । যদি আমরা বেসিকগুলি বুঝতে না পারি তবে এটি পরিচালনা করা খুব শক্ত হয়ে যায়।

এখানে একটি নিবন্ধ যা Looperজীবনচক্র, এটি কীভাবে ব্যবহার করতে হয় এবং এর ব্যবহার সম্পর্কে ব্যাখ্যা LooperকরেHandler

এখানে চিত্র বর্ণনা লিখুন

লুপার = থ্রেড + বার্তাকিউ


3
এটি ব্যাখ্যা করে না যে কেন কেউ এই ক্লাসটি ব্যবহার করবে, কেবল কীভাবে।
অ্যান্ড্রু কোস্টার

14

লুপার এবং হ্যান্ডলারের সংজ্ঞা:

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

বিবরণ:

সুতরাং পাইপলাইন থ্রেড হ'ল একটি থ্রেড যা হ্যান্ডলারের মাধ্যমে অন্যান্য থ্রেড থেকে আরও কাজ গ্রহণ করতে পারে।

Looper তাই নামকরণ করা হয়, কারণ এটি লুপ প্রয়োগ - পরবর্তী কাজের লাগে, এটা executes, তারপর পরের এক ইত্যাদি লাগে। হ্যান্ডলারটিকে হ্যান্ডলার বলা হয় কারণ এটি পরবর্তী কাজটি অন্য যে কোনও থ্রেড থেকে প্রতিবার হ্যান্ডেল বা গ্রহণ করতে এবং লুপারে (থ্রেড বা পাইপলাইন থ্রেড) পাস করার জন্য ব্যবহৃত হয়।

উদাহরণ:

লুপার এবং হ্যান্ডলার বা পাইপলাইন থ্রেডের খুব নিখুঁত উদাহরণ হ'ল ব্যাকগ্রাউন্ডে প্রতিটি নেটওয়ার্ক কলের জন্য একটি নতুন থ্রেড শুরু করার পরিবর্তে একাধিক চিত্র ডাউনলোড করা বা সেগুলিতে (এইচটিটিপি) একের পর এক আপলোড করা।

লুপার এবং হ্যান্ডলার এবং পাইপলাইন থ্রেডের সংজ্ঞা সম্পর্কে এখানে আরও পড়ুন:

অ্যান্ড্রয়েড সাহস: লুপার এবং হ্যান্ডলারের পরিচয়


7

একটি লুপার রয়েছে asynchronized MessageQueue যা কাতারে থাকা বার্তাগুলি প্রসেস করতে ব্যবহৃত হয়।

এটি প্রয়োগ করে a Thread নির্দিষ্ট স্টোরেজ প্যাটার্ন ।

Looperপ্রতি এক Thread। মূল পদ্ধতিগুলির মধ্যে রয়েছে prepare(), loop()এবংquit()

prepare()বর্তমান Threadহিসাবে একটি হিসাবে আরম্ভ করে Looper। ক্লাসটি নীচে প্রদর্শিত হিসাবে ব্যবহার করে prepare()এমন staticপদ্ধতি ThreadLocal

   public static void prepare(){
       ...
       sThreadLocal.set
       (new Looper());
   }
  1. prepare() ইভেন্টের লুপটি চালানোর আগে অবশ্যই স্পষ্টভাবে কল করা উচিত।
  2. loop()ইভেন্টের লুপটি চালায় যা নির্দিষ্ট থ্রেডের বার্তা পাঠানোর বার্তাগুলির জন্য অপেক্ষা করে। পরবর্তী বার্তাটি প্রাপ্ত হওয়ার পরে, loop()পদ্ধতিটি তার লক্ষ্য হ্যান্ডলারের কাছে বার্তা প্রেরণ করে
  3. quit()ইভেন্ট লুপ বন্ধ। এটি লুপটি শেষ করে না, পরিবর্তে এটি একটি বিশেষ বার্তা প্রেরণ করে

LooperThreadবেশ কয়েকটি পদক্ষেপের মাধ্যমে প্রোগ্রাম করা যায়

  1. প্রসারিত করা Thread

  2. Looper.prepare()একটি হিসাবে থ্রেড আরম্ভ করার জন্য কল করুনLooper

  3. Handlerআগত বার্তাগুলি প্রক্রিয়া করতে এক বা একাধিক (গুলি) তৈরি করুন

  4. Looper.loop()লুপটি না বলা পর্যন্ত বার্তাগুলি প্রক্রিয়া করার জন্য কল করুন quit()

5

পদ্ধতি শেষ হওয়ার পরে জাভা থ্রেডের আয়ু শেষ হয়েছে run()। একই থ্রেড আবার শুরু করা যায় না।

লুপারThread একটি বার্তা লুপে স্বাভাবিক রূপান্তরিত করে । এর মূল পদ্ধতিগুলি হ'ল Looper:

void prepare ()

লুপ হিসাবে বর্তমান থ্রেড শুরু করুন। এটি আপনাকে এমন হ্যান্ডলারগুলি তৈরি করার সুযোগ দেয় যা লুপটি শুরু করার আগে এই লুপটিকে রেফার করে। এই পদ্ধতিটি কল করার পরে লুপ () এ কল করতে ভুলবেন না এবং প্রস্থান () এ কল করে এটি শেষ করুন।

void loop ()

এই থ্রেডে বার্তা সারি চালান। লুপটি শেষ করতে কল () ছাড়ুন নিশ্চিত করুন।

void quit()

লুফার ছেড়ে দেয়।

বার্তা কাতারে আর কোনও বার্তা প্রক্রিয়াকরণ ছাড়াই লুপ () পদ্ধতিটি শেষ করতে দেয়।

জনিশরের এই মাইন্ডরস যুক্ত নিবন্ধটি মূল ধারণাটি সুন্দর উপায়ে ব্যাখ্যা করেছে।

এখানে চিত্র বর্ণনা লিখুন

Looperএকটি থ্রেডের সাথে যুক্ত। আপনার যদি Looperইউআই থ্রেডের প্রয়োজন হয় তবে Looper.getMainLooper()যুক্ত থ্রেডটি ফিরে আসবে।

আপনাকে Looperকোনও হ্যান্ডলারের সাথে যুক্ত হতে হবে ।

Looper, Handlerএবং HandlerThreadঅ্যাসিক্রোনাস প্রোগ্রামিংয়ের সমস্যাগুলি সমাধান করার জন্য অ্যান্ড্রয়েডের উপায়।

একবার আপনার হয়ে গেলে Handler, আপনি নীচে API গুলি কল করতে পারেন।

post (Runnable r)

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

boolean sendMessage (Message msg)

বর্তমান সময়ের আগে সমস্ত মুলতুবি থাকা বার্তাগুলির পরে বার্তাটির সারিটির শেষে একটি বার্তাটিকে চাপ দেয়। এই হ্যান্ডলারের সাথে সংযুক্ত থ্রেডে এটি হ্যান্ডেলমেজ (বার্তা) এ প্রাপ্ত হবে।

HandlerThread একটি নতুন থ্রেড শুরু করার জন্য ক্লাস যা একটি লুপ রয়েছে। লুপারটি হ্যান্ডলার ক্লাস তৈরি করতে ব্যবহৃত হতে পারে

কিছু পরিস্থিতিতে আপনি Runnableইউআই থ্রেডে টাস্কগুলি চালাতে পারবেন না । যেমন নেটওয়ার্ক অপারেশন: একটি সকেটে বার্তা প্রেরণ করুন, একটি URL খুলুন এবং পড়ার মাধ্যমে সামগ্রী পান contentInputStream

এই ক্ষেত্রে, HandlerThreadদরকারী। আপনি পেতে পারেন Looperথেকে অবজেক্ট HandlerThreadএবং একটি তৈরি Handlerউপর HandlerThreadপ্রধান থ্রেডের পরিবর্তে।

HandlerThread কোডটির এই মত হবে:

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

উদাহরণস্বরূপ কোডের জন্য নীচের পোস্টটি দেখুন:

অ্যান্ড্রয়েড: একটি থ্রেড টোস্ট


5

লুপারের থ্রেডগুলি বোঝা

একটি জাভা কার্যকর করার একটি ইউনিট থ্রেড করে যা তার রান () পদ্ধতিতে কোনও কার্য সম্পাদন এবং তার পরে সমাপ্ত করার জন্য ডিজাইন করা হয়েছিল: এখানে চিত্র বর্ণনা লিখুন

তবে অ্যান্ড্রয়েডে এমন অনেকগুলি ব্যবহারের ঘটনা রয়েছে যেখানে আমাদের একটি থ্রেডকে জীবিত রাখতে হবে এবং উদাহরণস্বরূপ ব্যবহারকারীর ইনপুট / ইভেন্টের জন্য অপেক্ষা করতে হবে। ইউআই থ্রেড ওরফেMain Thread

অ্যান্ড্রয়েডের মূল থ্রেড হ'ল একটি জাভা থ্রেড যা প্রথমে JVM দ্বারা একটি অ্যাপ্লিকেশন প্রবর্তন শুরু হয়েছিল এবং ব্যবহারকারী এটি বন্ধ না করা বা অযাচিত ব্যতিক্রমের মুখোমুখি না হওয়া অবধি চালিয়ে যেতে থাকে।

যখন একটি অ্যাপ্লিকেশন চালু করা হয়, সিস্টেমটি অ্যাপ্লিকেশনটির জন্য মৃত্যুদন্ড কার্যকর করার একটি থ্রেড তৈরি করে, "মেন" নামে পরিচিত। এই থ্রেডটি অত্যন্ত গুরুত্বপূর্ণ কারণ এটি অঙ্কন ইভেন্টগুলি সহ উপযুক্ত ব্যবহারকারী ইন্টারফেস উইজেটে ইভেন্ট প্রেরণের দায়িত্বে রয়েছে।

এখানে চিত্র বর্ণনা লিখুন

এখন এখানে লক্ষ্য করুন যে যদিও মূল থ্রেডটি জাভা থ্রেড তবে এটি ব্যবহারকারীর ইভেন্টগুলি শুনতে থাকে এবং পর্দায় 60 fps ফ্রেম আঁকতে থাকে এবং এখনও এটি প্রতিটি চক্রের পরে মারা যায় না। এটা কিভাবে?

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

ডিফল্টরূপে থ্রেডগুলির সাথে একটি বার্তা লুপ থাকে না তবে রান পদ্ধতিতে আপনি Looper.prepare () কে কল করে এবং তারপরে Looper.loop () এ কল করে একটি বরাদ্দ করতে পারেন।

লুপারের উদ্দেশ্য হ'ল একটি থ্রেডটি জীবিত রাখা এবং Messageগণনা সম্পাদনের জন্য ইনপুট অবজেক্টের পরবর্তী চক্রের জন্য অপেক্ষা করা যা অন্যথায় কার্যকর হওয়ার প্রথম চক্রের পরে ধ্বংস হয়ে যায়।

আপনি যদি লুপার কীভাবে Messageঅবজেক্ট সারিটি পরিচালনা করেন তা আরও গভীরভাবে আবিষ্কার করতে চান তবে আপনার উত্সের কোডটি একবার দেখে নিতে পারেন Looperclass:

https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/os/Looper.java

নীচে আপনি কীভাবে ক্লাস ব্যবহার করে একটি তৈরি করতে Looper Threadএবং যোগাযোগ করতে পারেন তার একটি উদাহরণActivityLocalBroadcast

class LooperThread : Thread() {

    // sendMessage success result on UI
    private fun sendServerResult(result: String) {
        val resultIntent = Intent(ServerService.ACTION)
        resultIntent.putExtra(ServerService.RESULT_CODE, Activity.RESULT_OK)
        resultIntent.putExtra(ServerService.RESULT_VALUE, result)
        LocalBroadcastManager.getInstance(AppController.getAppController()).sendBroadcast(resultIntent)
    }

    override fun run() {
        val looperIsNotPreparedInCurrentThread = Looper.myLooper() == null

        // Prepare Looper if not already prepared
        if (looperIsNotPreparedInCurrentThread) {
            Looper.prepare()
        }

        // Create a handler to handle messaged from Activity
        handler = Handler(Handler.Callback { message ->
            // Messages sent to Looper thread will be visible here
            Log.e(TAG, "Received Message" + message.data.toString())

            //message from Activity
            val result = message.data.getString(MainActivity.BUNDLE_KEY)

            // Send Result Back to activity
            sendServerResult(result)
            true
        })

        // Keep on looping till new messages arrive
        if (looperIsNotPreparedInCurrentThread) {
            Looper.loop()
        }
    }

    //Create and send a new  message to looper
    fun sendMessage(messageToSend: String) {
        //Create and post a new message to handler
        handler!!.sendMessage(createMessage(messageToSend))
    }


    // Bundle Data in message object
    private fun createMessage(messageToSend: String): Message {
        val message = Message()
        val bundle = Bundle()
        bundle.putString(MainActivity.BUNDLE_KEY, messageToSend)
        message.data = bundle
        return message
    }

    companion object {
        var handler: Handler? = null // in Android Handler should be static or leaks might occur
        private val TAG = javaClass.simpleName

    }
}

ব্যবহার :

 class MainActivity : AppCompatActivity() {

    private var looperThread: LooperThread? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // start looper thread
        startLooperThread()

        // Send messages to Looper Thread
        sendMessage.setOnClickListener {

            // send random messages to looper thread
            val messageToSend = "" + Math.random()

            // post message
            looperThread!!.sendMessage(messageToSend)

        }   
    }

    override fun onResume() {
        super.onResume()

        //Register to Server Service callback
        val filterServer = IntentFilter(ServerService.ACTION)
        LocalBroadcastManager.getInstance(this).registerReceiver(serverReceiver, filterServer)

    }

    override fun onPause() {
        super.onPause()

        //Stop Server service callbacks
     LocalBroadcastManager.getInstance(this).unregisterReceiver(serverReceiver)
    }


    // Define the callback for what to do when data is received
    private val serverReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val resultCode = intent.getIntExtra(ServerService.RESULT_CODE, Activity.RESULT_CANCELED)
            if (resultCode == Activity.RESULT_OK) {
                val resultValue = intent.getStringExtra(ServerService.RESULT_VALUE)
                Log.e(MainActivity.TAG, "Server result : $resultValue")

                serverOutput.text =
                        (serverOutput.text.toString()
                                + "\n"
                                + "Received : " + resultValue)

                serverScrollView.post( { serverScrollView.fullScroll(View.FOCUS_DOWN) })
            }
        }
    }

    private fun startLooperThread() {

        // create and start a new LooperThread
        looperThread = LooperThread()
        looperThread!!.name = "Main Looper Thread"
        looperThread!!.start()

    }

    companion object {
        val BUNDLE_KEY = "handlerMsgBundle"
        private val TAG = javaClass.simpleName
    }
}

আমরা কি এর পরিবর্তে অ্যাসিঙ্ক টাস্ক বা ইনটেন্ট পরিষেবাদি ব্যবহার করতে পারি?

  • অ্যাসিঙ্ক কার্যগুলি পটভূমিতে একটি সংক্ষিপ্ত ক্রিয়াকলাপ সম্পাদন এবং UI থ্রেডে অগ্রগতি এবং ফলাফল দেওয়ার জন্য ডিজাইন করা হয়েছে। অ্যাসিঙ্ক কার্যগুলিতে সীমাবদ্ধতা রয়েছে যেমন আপনি 128 টিরও বেশি এ্যাসিঙ্ক কার্য তৈরি করতে পারবেন না এবং ThreadPoolExecutorকেবল 5 টি এসিঙ্ক কার্যের অনুমতি দেবে ।

  • IntentServicesএছাড়াও আরও দীর্ঘ সময়ের জন্য ব্যাকগ্রাউন্ড টাস্ক করার জন্য ডিজাইন করা হয়েছে এবং আপনি LocalBroadcastযোগাযোগ করতে ব্যবহার করতে পারেন Activity। কিন্তু কার্য সম্পাদনের পরে পরিষেবাগুলি ধ্বংস হয়ে যায়। আপনি যদি এটি দীর্ঘকাল ধরে চালিয়ে যেতে চান তবে আপনার প্রয়োজন মতো হেকস করা দরকার while(true){...}

লুপার থ্রেডের জন্য অন্যান্য অর্থবহ ব্যবহারের ক্ষেত্রে:

  • 2 ওয়ে সকেট যোগাযোগের জন্য ব্যবহৃত হয় যেখানে সার্ভার ক্লায়েন্টের সকেট শুনতে থাকে এবং স্বীকৃতি ফিরিয়ে দেয়

  • পটভূমিতে বিটম্যাপ প্রক্রিয়াজাতকরণ। চিত্রের url কে লুপার থ্রেডে পাস করুন এবং এটি ফিল্টার প্রভাব প্রয়োগ করবে এবং এটিকে টিমে ররি অবস্থানে সংরক্ষণ করবে এবং তারপরে চিত্রটির অস্থায়ী পথ সম্প্রচার করবে।


4

এই প্রশ্নের প্রশ্নের কোনও যোগসূত্র নেই, তবে লুপার ব্যবহার এবং লোকেরা যেভাবে এই সমস্ত উত্তরগুলিতে হ্যান্ডলার এবং লুপার তৈরি করেছে সেগুলি এখানে সরল খারাপ অনুশীলন (কিছু ব্যাখ্যা সঠিক হলেও), আমাকে এই পোস্ট করতে হবে:

HandlerThread thread = new HandlerThread(threadName);
thread.start();
Looper looper = thread.getLooper();
Handler myHandler = new Handler(looper);

এবং একটি সম্পূর্ণ বাস্তবায়নের জন্য


3

কোনও পরিষেবাতে একাধিক ডাউন বা আইটেম আপলোড হওয়াই আরও ভাল উদাহরণ।

Handlerএবং AsnycTaskপ্রায়শই ইউআই (থ্রেড) এবং একটি কর্মী থ্রেডের মধ্যে ইভেন্ট / বার্তা প্রচার করতে বা ক্রিয়া বিলম্বিত করতে ব্যবহৃত হয় delay সুতরাং এগুলি ইউআইয়ের সাথে আরও সম্পর্কিত।

একজন Looperহ্যান্ডলগুলি কাজের (যেমন Runnables, ফিউচার ) ব্যাকগ্রাউন্ডে একটি থ্রেড সম্পর্কিত সারিতে - এমনকি কোনো ব্যবহারকারী মিথস্ক্রিয়া সঙ্গে বা UI 'তে প্রদর্শিত (অ্যাপ্লিকেশন ডাউনলোড একটি কল চলাকালীন পটভূমিতে একটি ফাইল)।


1

লুপার কী?

ডকস থেকে

Looper

Looperক্লাস একটি জন্য একটি বার্তা লুপ চালানো ব্যবহৃত thread। ডিফল্টরূপে থ্রেডগুলির সাথে একটি বার্তা লুপ থাকে না; একটি তৈরি করতে, prepare()লুপটি চালানোর জন্য যে থ্রেডে কল করুন এবং তারপরে loop()লুপটি বন্ধ না হওয়া পর্যন্ত বার্তা প্রসেস করা হবে।

  • Looperহ'ল একটি বার্তা হ্যান্ডলিং লুপ:
  • লুপারের একটি গুরুত্বপূর্ণ চরিত্রটি এটি যে থ্রেডের সাথে লুপ তৈরি করা হয়েছে তার সাথে এটি জড়িত
  • লুপার শ্রেণি একটি রক্ষণাবেক্ষণ করে MessageQueueযা একটি তালিকা বার্তা ধারণ করে। লুপারের একটি গুরুত্বপূর্ণ চরিত্রটি এটি যে থ্রেডের সাথে লুপ তৈরি করা হয়েছে তার সাথে এটি জড়িত।
  • Looperতাই নামে করা হয়েছে কারণ এটি লুপ প্রয়োগ করা হয় - পরবর্তী কাজের লাগে, এটা executes, তারপর পরের এক ইত্যাদি লাগে। Handlerএকটি হ্যান্ডলার বলা হয় কারণ কেউ একটি ভাল নাম উদ্ভাবিত করতে পারেনি
  • অ্যান্ড্রয়েড Looperহ'ল অ্যান্ড্রয়েড ব্যবহারকারী ইন্টারফেসের মধ্যে জাভা ক্লাস যা হ্যান্ডলার ক্লাসের সাথে একসাথে ইউআই ইভেন্টগুলি যেমন বোতাম ক্লিকগুলি, স্ক্রীন পুনরায় আঁকা এবং ওরিয়েন্টেশন সুইচগুলি প্রক্রিয়া করতে পারে।

কিভাবে এটা কাজ করে?

এখানে চিত্র বর্ণনা লিখুন

লুপার তৈরি করা হচ্ছে

একটি থ্রেড আসে Looperএবং তার চলমান পরে MessageQueueকল Looper.prepare()করে। Looper.prepare()কলিং থ্রেড সনাক্ত করে, একটি লুপার তৈরি করে এবং MessageQueueবস্তুকে থ্রেড যুক্ত করে

কোডের উদাহরণ

class MyLooperThread extends Thread {

      public Handler mHandler; 

      public void run() { 

          // preparing a looper on current thread  
          Looper.prepare();

          mHandler = new Handler() { 
              public void handleMessage(Message msg) { 
                 // process incoming messages here
                 // this will run in non-ui/background thread
              } 
          }; 

          Looper.loop();
      } 
  }

আরও তথ্যের জন্য পোস্টের নীচে চেক করুন


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