কীভাবে 'android.os.NetworkOnMainThreadException' ঠিক করবেন?


2391

RssReader এর জন্য আমার অ্যান্ড্রয়েড প্রকল্প চালানোর সময় আমি একটি ত্রুটি পেয়েছি।

কোড:

URL url = new URL(urlToRssFeed);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlreader = parser.getXMLReader();
RssHandler theRSSHandler = new RssHandler();
xmlreader.setContentHandler(theRSSHandler);
InputSource is = new InputSource(url.openStream());
xmlreader.parse(is);
return theRSSHandler.getFeed();

এবং এটি নীচের ত্রুটি দেখায়:

android.os.NetworkOnMainThreadException

আমি কীভাবে এই সমস্যাটি সমাধান করতে পারি?


131
আরও তথ্যের জন্য এই ব্লগ পোস্টটি নেটওয়ার্কঅনমেনথ্রেডএক্সসেপ্টে পড়ুন। এটি ব্যাখ্যা করে যে এন্ড্রয়েড 3.0.০ এবং তারপরেও কেন ঘটে।
অ্যাড্রিয়ান সন্ন্যাসী

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

3
অনেকগুলি বিকল্প গ্রন্থাগার রয়েছে যা এই সমস্যাটি সমাধান করে। অনেক এই পৃষ্ঠার নীচে তালিকাভুক্ত করা হয় । আপনি যদি আরও কিছু পান তবে আমরা সেগুলি গ্রহণ করি :)
স্নিকোলস

আপনাকে মূল (ইউআই) থ্রেড থেকে আলাদা একটি থ্রেডে ইন্টারনেট ক্রিয়াকলাপ পরিচালনা করতে হবে
নাভিদ আহমেদ

"অ্যান্ড্রয়েডের পূর্ববর্তী সংস্করণগুলিতে ত্রুটির কারণে সিস্টেমটি মূল থ্রেডে কোনও টিসিপি সকেটে লিখিতিকে কঠোর মোড লঙ্ঘন হিসাবে পতাকাঙ্কিত করে না Android NetworkOnMainThreadException। " - সুতরাং আমাদের মধ্যে কিছু সম্প্রতি পর্যন্ত এটি আঘাত না! বিকাশকারী.অ্যান্ড্রয়েড.
জয়

উত্তর:


2547

কোনও অ্যাপ্লিকেশন যখন তার মূল থ্রেডে নেটওয়ার্কিং অপারেশন করার চেষ্টা করে তখন এই ব্যতিক্রম ছুঁড়ে দেওয়া হয়। এতে আপনার কোড চালান AsyncTask:

class RetrieveFeedTask extends AsyncTask<String, Void, RSSFeed> {

    private Exception exception;

    protected RSSFeed doInBackground(String... urls) {
        try {
            URL url = new URL(urls[0]);
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            XMLReader xmlreader = parser.getXMLReader();
            RssHandler theRSSHandler = new RssHandler();
            xmlreader.setContentHandler(theRSSHandler);
            InputSource is = new InputSource(url.openStream());
            xmlreader.parse(is);

            return theRSSHandler.getFeed();
        } catch (Exception e) {
            this.exception = e;

            return null;
        } finally {
            is.close();
        }
    }

    protected void onPostExecute(RSSFeed feed) {
        // TODO: check this.exception
        // TODO: do something with the feed
    }
}

কীভাবে টাস্কটি কার্যকর করবেন:

ইন MainActivity.javaফাইল আপনি আপনার মধ্যে এই লাইন যোগ করতে পারেন oncreate()পদ্ধতি

new RetrieveFeedTask().execute(urlToRssFeed);

এটিকে AndroidManifest.xmlফাইলটিতে যুক্ত করতে ভুলবেন না :

<uses-permission android:name="android.permission.INTERNET"/>

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

4
প্রকৃতপক্ষে আমি আপনার উপরে উল্লিখিত হিসাবে একই জিনিসটি করেছি তবে আমি এই ত্রুটির মুখোমুখি জাভা.লং.রুনটাইম এক্সসেপশন: থ্রেডের ভিতরে হ্যান্ডলার তৈরি করতে পারি না যা লুপার.প্রিপ্রে () বলে না
ধ্রুব ত্যাগী

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

5
সাবধানতা, AsyncTask প্রায়শই প্রতিটি ক্রিয়াকলাপের নেটওয়ার্ক ক্রিয়াকলাপের জন্য ব্যবহার করা হয় যখন তা হওয়া উচিত নয়। এর জীবনচক্রটি ক্রিয়াকলাপের সাথে সুসংগত নয়। ডেটা আনার জন্য, আপনাকে ভিউটির পিছনে একটি ইনটেন্স সার্ভিস এবং ডাটাবেস ব্যবহার করা উচিত।
ব্রিল প্যাপিন 21

1
@ ব্রিলপ্যাপিন, এফডাব্লুআইডাব্লু, এই অ্যান্ড্রয়েড বিকাশকারী গাইড ব্যবহার করে AsyncTaskএবং একটি কনফিগারেশন পরিবর্তনের যত্ন নেয়।
ওহে জুড

676

আপনার প্রায় সবসময় একটি থ্রেড বা একটি অ্যাসিনক্রোনাস টাস্ক হিসাবে নেটওয়ার্ক ক্রিয়াকলাপ চালানো উচিত।

তবে তা হয় এই বিধিনিষেধ অপসারণ সম্ভব এবং আপনি যদি ফলাফলগুলি মানতে রাজি হন তবে আপনি ডিফল্ট আচরণকে ওভাররাইড করে।

যোগ করুন

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

StrictMode.setThreadPolicy(policy); 

আপনার ক্লাসে,

এবং

এই অনুমতিটি অ্যান্ড্রয়েড ম্যানিফেস্ট.এক্সএমএল ফাইলটিতে যুক্ত করুন:    

<uses-permission android:name="android.permission.INTERNET"/>

ফল:

আপনার অ্যাপ্লিকেশনটি (স্পটি ইন্টারনেট সংযোগের ক্ষেত্রগুলিতে) প্রতিক্রিয়াহীন হয়ে উঠবে এবং লকআপ হয়ে যাবে, ব্যবহারকারী আস্তে আস্তে বুঝতে পারে এবং তাকে জোর করে হত্যা করতে হবে এবং আপনি ক্রিয়াকলাপ ব্যবস্থাপককে আপনার অ্যাপ্লিকেশনটি মেরে ফেলতে এবং ব্যবহারকারীকে বলবেন যে অ্যাপটি বন্ধ হয়ে গেছে।

অ্যান্ড্রয়েড সংবেদনশীলতা জন্য ডিজাইন করার ভাল প্রোগ্রামিং অভ্যাস কিছু ভাল টিপ্স আছে: http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html


455
এটি একটি খুব খারাপ ধারণা। সমাধানটি হ'ল মূল থ্রেডে নেটওয়ার্ক আইও এড়ানো (যেমন স্বীকৃত উত্তরটি দেখায়)।
এমবিআইডি

74
এটির সাহায্যে আপনি কেবল আপনার আসল সমস্যাটি লুকিয়ে রাখবেন।
অ্যালেক্স

28
@TwistedUmbrella AsyncTask কোডের একটি পৃষ্ঠা যুক্ত করে না, এতে lines টি লাইন যুক্ত হয় (শ্রেণির ঘোষণা, টীকাটি বিভক্তকরণ, doInBackgroundঘোষণা, ২ টি বন্ধনী বন্ধনী এবং একটি কল execute())। অন্যদিকে, আপনি যেমন উল্লেখ করেছেন তেমন কোনও সাইট থেকে একক আনাও ইউআই প্রতিক্রিয়াশীলতায় একটি উল্লেখযোগ্য পিছনে আনে। অলসতা করবেন না।
Zoltán

19
আমি মনে করি এটি সঠিক সমাধান যদি আপনি ঠিক কোডের একটি নমুনা অংশ চালানোর জন্য সন্ধান করছেন তবে সঠিক অ্যাসিঙ্কটাস্ক বাস্তবায়নের আগে কিছু কাজ করে কিনা see এই কারণেই আমি এই উত্তরটিকে উঁচু করে তুলেছি, যদিও অন্যরা যেমনটি বলেছে, এটি কোনও প্রোডাক্ট অ্যাপে করা উচিত নয়, কেবলমাত্র একটি দেব পরীক্ষার জন্য দ্রুত কাজ হিসাবে ar
hooked82

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

427

আমি একটি নতুন ব্যবহার করে এই সমস্যাটি সমাধান করেছি Thread

Thread thread = new Thread(new Runnable() {

    @Override
    public void run() {
        try  {
            //Your code goes here
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});

thread.start(); 

7
আপনি যখনই কোনও নেটওয়ার্ক অপারেশন করতে চান প্রতিবার নতুন থ্রেড তৈরি করার পরিবর্তে আপনি একটি একক থ্রেড এক্সিকিউটার পরিষেবাও ব্যবহার করতে পারেন।
অ্যালেক্স লকউড

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

1
@ স্টেভি কিভাবে অগ্রাধিকার সেট করবেন? চালানো বা এক্সিকিউটর সার্ভিসের কোনওরকম সেটার পদ্ধতি নেই
জে.কে

1
@ জে কে আপনার এক্সিকিউটর সার্ভিসটিকে একটি কাস্টম থ্রেডফ্যাক্টরি সরবরাহ করুন এবং ফেরত দেওয়ার আগে থ্রেডে থ্রেড.সেটপ্রাইরিটি কল করুন।
স্টেভি

1
"সরাসরি অ্যান্ড্রয়েডে থ্রেডগুলি ব্যবহার করা নিরুত্সাহিত করা হয়েছে It এটি সমাধানের চেয়ে আরও সমস্যার সৃষ্টি করে" এর উপর বিস্তৃত হওয়ার যত্ন? প্রকৃতপক্ষে অ্যাসিঙ্কটাস্ককে হুবহু হ্রাস করা হচ্ছে ... techyourchance.com/asynctask-drecated
Fran Marzoa

169

গৃহীত উত্তরের কয়েকটি উল্লেখযোগ্য ডাউন-সাইড রয়েছে। আপনি কী করছেন তা যদি আপনি সত্যই না জেনে থাকেন তবে নেটওয়ার্কিংয়ের জন্য অ্যাসিঙ্কটাস্ক ব্যবহার করা ভাল নয় । নিম্ন-দিকের কয়েকটি অন্তর্ভুক্ত:

  • অ্যাসিঙ্কটাস্কের অ স্থিতিশীল অভ্যন্তর শ্রেণীরূপে তৈরির সাথে ঘেরযুক্ত কার্যকলাপের বস্তু, তার প্রসঙ্গ এবং সেই ক্রিয়াকলাপের দ্বারা নির্মিত পুরো ভিউ হায়ারার্কির অন্তর্নিহিত উল্লেখ রয়েছে। AsyncTask এর ব্যাকগ্রাউন্ডের কাজ শেষ না হওয়া অবধি এই রেফারেন্সটি ক্রিয়াকলাপটিকে সংগ্রহ করা থেকে আটকাতে বাধা দেয়। যদি ব্যবহারকারীর সংযোগটি ধীর গতিতে হয় এবং / অথবা ডাউনলোডটি বড় হয় তবে এই স্বল্প-মেয়াদী মেমরি লিক একটি সমস্যা হয়ে উঠতে পারে - উদাহরণস্বরূপ, যদি ওরিয়েন্টেশনটি বেশ কয়েকবার পরিবর্তিত হয় (এবং আপনি নির্বাহী কার্যগুলি বাতিল করেন না), বা ব্যবহারকারী কার্যকলাপ থেকে দূরে নেভিগেট।
  • AsyncTask এর প্রয়োগ করা প্ল্যাটফর্মের উপর নির্ভর করে বিভিন্ন নির্বাহের বৈশিষ্ট্য রয়েছে: API স্তর 4 এর আগে AsyncTasks একক পটভূমির থ্রেডে ক্রমিকভাবে সম্পাদন করে; এপিআই লেভেল 4 থেকে এপিআই লেভেল 10 এর মাধ্যমে, অ্যাসিঙ্কটাস 128 থ্রেড পর্যন্ত একটি পুলের উপর কার্যকর; এপিআই স্তর ১১ এর পর থেকে অ্যাসিঙ্কটাস্ক একক পটভূমির থ্রেডে সিরিয়ালি কার্যকর করে (যদি না আপনি ওভারলোডেড executeOnExecutorপদ্ধতিটি ব্যবহার করেন এবং বিকল্প নির্বাহকের সরবরাহ না করেন)। আইসিএসে ক্রমিকভাবে চলমান চলাকালীন যে কোডটি সূক্ষ্মভাবে কাজ করে তা জিঞ্জারব্রেডে একযোগে কার্যকর করা হলে ভেঙে যেতে পারে, বলুন আপনার যদি অজান্তে অর্ডার অফ-এক্সিকিউশন নির্ভরতা থাকে।

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

  1. আপনার জন্য এটি একটি দুর্দান্ত কাজ করে এমন একটি লাইব্রেরি ব্যবহার করে - এই প্রশ্নে নেটওয়ার্কিং লিবের একটি দুর্দান্ত তুলনা আছে , বা
  2. কোনও Serviceবা IntentServiceপরিবর্তে ব্যবহার করে, সম্ভবত PendingIntentক্রিয়াকলাপের onActivityResultপদ্ধতির মাধ্যমে ফলাফলটি ফেরত পাঠাতে ।

ইনট্যানসেসর পদ্ধতি

নিচে-পক্ষের:

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

আপ-পক্ষের:

  • স্বল্পমেয়াদী মেমরি ফাঁস সমস্যা এড়ায়
  • আপনার ক্রিয়াকলাপটি যদি নেটওয়ার্ক অপারেশনগুলি ফ্লাইটে থাকা অবস্থায় পুনরায় চালু হয় তবে এটি এর মাধ্যমে ডাউনলোডের ফলাফলটি পেতে পারে onActivityResult পদ্ধতির
  • দৃust় নেটওয়ার্কিং কোডটি তৈরি এবং পুনরায় ব্যবহার করতে অ্যাসিঙ্কটাস্কের থেকে ভাল প্ল্যাটফর্ম। উদাহরণ: আপনার যদি কোনও গুরুত্বপূর্ণ আপলোড করার দরকার হয় তবে আপনি এটি AsyncTaskএকটি থেকে শুরু করতে পারেন Activity, তবে ব্যবহারকারী যদি ফোন কল নিতে অ্যাপ্লিকেশনটির বাইরে চলে যায়, আপলোডটি সম্পূর্ণ হওয়ার আগে সিস্টেম অ্যাপটিকে মেরে ফেলতে পারে । এটা সম্ভাবনা কম একটি সক্রিয় সঙ্গে একটি অ্যাপ্লিকেশন হত্যা করতে Service
  • আপনি যদি নিজের নিজস্ব সাম্প্রতিক সংস্করণ ব্যবহার করেন IntentService(যেমন আমি উপরে লিঙ্ক করেছি তার মতো) আপনি এর মাধ্যমে সমাবর্তনের স্তরটি নিয়ন্ত্রণ করতে পারেন Executor

বাস্তবায়ন সংক্ষিপ্তসার

আপনি IntentServiceএকক ব্যাকগ্রাউন্ড থ্রেডে ডাউনলোডগুলি সম্পাদন করতে খুব সহজেই বাস্তবায়ন করতে পারেন।

পদক্ষেপ 1: IntentServiceডাউনলোড সম্পাদন করতে একটি তৈরি করুন । Intentঅতিরিক্তের মাধ্যমে কী ডাউনলোড করবেন তা আপনি এটি বলতে PendingIntentপারেন এবং ফলাফলটি ফেরত দেওয়ার জন্য এটি ব্যবহার করতে পারেন Activity:

import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Intent;
import android.util.Log;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

public class DownloadIntentService extends IntentService {

    private static final String TAG = DownloadIntentService.class.getSimpleName();

    public static final String PENDING_RESULT_EXTRA = "pending_result";
    public static final String URL_EXTRA = "url";
    public static final String RSS_RESULT_EXTRA = "url";

    public static final int RESULT_CODE = 0;
    public static final int INVALID_URL_CODE = 1;
    public static final int ERROR_CODE = 2;

    private IllustrativeRSSParser parser;

    public DownloadIntentService() {
        super(TAG);

        // make one and re-use, in the case where more than one intent is queued
        parser = new IllustrativeRSSParser();
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        PendingIntent reply = intent.getParcelableExtra(PENDING_RESULT_EXTRA);
        InputStream in = null;
        try {
            try {
                URL url = new URL(intent.getStringExtra(URL_EXTRA));
                IllustrativeRSS rss = parser.parse(in = url.openStream());

                Intent result = new Intent();
                result.putExtra(RSS_RESULT_EXTRA, rss);

                reply.send(this, RESULT_CODE, result);
            } catch (MalformedURLException exc) {
                reply.send(INVALID_URL_CODE);
            } catch (Exception exc) {
                // could do better by treating the different sax/xml exceptions individually
                reply.send(ERROR_CODE);
            }
        } catch (PendingIntent.CanceledException exc) {
            Log.i(TAG, "reply cancelled", exc);
        }
    }
}

পদক্ষেপ 2: ম্যানিফেস্টে পরিষেবাটি নিবন্ধ করুন:

<service
        android:name=".DownloadIntentService"
        android:exported="false"/>

পদক্ষেপ 3: পরিষেবাটি ফলাফলটি ফেরত দিতে ব্যবহার করবে এমন একটি পেন্ডিং রেজাল্ট অবজেক্টটি পাস করে ক্রিয়াকলাপ থেকে পরিষেবাটি আহ্বান করুন:

PendingIntent pendingResult = createPendingResult(
    RSS_DOWNLOAD_REQUEST_CODE, new Intent(), 0);
Intent intent = new Intent(getApplicationContext(), DownloadIntentService.class);
intent.putExtra(DownloadIntentService.URL_EXTRA, URL);
intent.putExtra(DownloadIntentService.PENDING_RESULT_EXTRA, pendingResult);
startService(intent);

পদক্ষেপ 4: কার্যকারিতা ফলাফলের ফলাফলটি হ্যান্ডেল করুন:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == RSS_DOWNLOAD_REQUEST_CODE) {
        switch (resultCode) {
            case DownloadIntentService.INVALID_URL_CODE:
                handleInvalidURL();
                break;
            case DownloadIntentService.ERROR_CODE:
                handleError(data);
                break;
            case DownloadIntentService.RESULT_CODE:
                handleRSS(data);
                break;
        }
        handleRSS(data);
    }
    super.onActivityResult(requestCode, resultCode, data);
}

একটি সম্পূর্ণ কার্যকারী অ্যান্ড্রয়েড-স্টুডিও / গ্রেডেল প্রকল্পযুক্ত একটি গিথুব প্রকল্প এখানে উপলভ্য ।


ইনটেন্ট সার্ভিস হ'ল এটি করার সঠিক উপায়, উপড়ে নেওয়া নয় কারণ অ্যাসিঙ্কটাস্ক এটি না করার ঠিক উপায়।
ব্রিল প্যাপিন

3
@ ব্রিলপ্যাপিন আমি প্রায় সম্পূর্ণরূপে একমত এবং অ্যাসিঙ্কটাসকের অসুবিধাগুলির উপর জোর দেওয়ার জন্য আমি আবারও শব্দটি দিয়েছি। (আমি এখনও মনে আছে খুব ছোট যেখানে মামলার সংখ্যা - আপনি সত্যিই জানতে আপনি কি করছেন - এটা হতে পারে হতে ঠিক আছে AsyncTask ব্যবহার করতে, কিন্তু গৃহীত উত্তর কোনো অপূর্ণতা বাতলান করে না এবং ভাল জন্য খুব জনপ্রিয় উপায় Android এর)।
স্টিভি

1
আপনার আসলে কি দরকার IllustrativeRSS? আপনি আরএসএস স্টাফ নিয়ে কাজ না করলে কী হবে?
কুল্লব

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

আমি কেবল এটিই বলতে যাচ্ছি: এই উত্তরটি আরও ভাল বিকল্পের চেয়ে প্রকল্পটি ভাগ করে নেওয়ার আরও এক উপায় বলে মনে হচ্ছে AsyncTask। ত্রুটিটি হ'ল বিকাশকারীদের ইউআই থেকে পিছিয়ে থাকা থেকে বিরত রাখা, অগত্যা তাদের গোটা উদ্দেশ্য / পরিষেবাদি দিয়ে সুরক্ষার ঝুঁকি নিয়ে প্রবৃত্ত হওয়া উচিত নয়।
পরিত্যক্ত কার্ট

144

আপনি মধুচক্রের ইউআই থ্রেডে নেটওয়ার্ক I / O সঞ্চালন করতে পারবেন না । প্রযুক্তিগতভাবে, এটি হয় Android এর পূর্ববর্তী সংস্করণের উপর সম্ভব, কিন্তু এটি একটি সত্যিই খারাপ ধারণা হিসাবে এটি আপনার অ্যাপ্লিকেশন সাড়া না করার কারণ হবে, এবং অপারেটিং সিস্টেম খারাপভাবে ভদ্র হচ্ছে আপনার অ্যাপ হত্যা হতে পারে। ব্যাকগ্রাউন্ড থ্রেডে আপনার নেটওয়ার্ক লেনদেন সম্পাদন করতে আপনাকে একটি পটভূমি প্রক্রিয়া চালাতে হবে বা অ্যাসিঙ্কটাস্ক ব্যবহার করতে হবে।

অ্যান্ড্রয়েড বিকাশকারী সাইটে পেইনলেস থ্রেডিং সম্পর্কে একটি নিবন্ধ রয়েছে যা এটির একটি ভাল ভূমিকা এবং এটি আপনাকে এখানে বাস্তবের তুলনায় আরও উত্তম গভীরতার সাথে উত্তর সরবরাহ করবে than


76
  1. কড়া মোড ব্যবহার করবেন না (কেবলমাত্র ডিবাগ মোডে)
  2. এসডিকে সংস্করণটি পরিবর্তন করবেন না
  3. আলাদা থ্রেড ব্যবহার করবেন না

পরিষেবা বা অ্যাসিঙ্কটাস্ক ব্যবহার করুন

ওভারফ্লো প্রশ্ন স্ট্যাক এছাড়াও দেখুন:

android.os.NetworkOnMainThreadException অ্যান্ড্রয়েড থেকে ইমেল প্রেরণ


8
সম্ভবত এই বিষয়টিকে গুরুত্ব দেওয়ার মতো যে আপনি যদি কোনও পরিষেবা ব্যবহার করেন তবে আপনাকে একটি পৃথক থ্রেড তৈরি করতে হবে - পরিষেবা কলব্যাকগুলি মূল থ্রেডে চালিত। অন্যদিকে একটি ইনটেন্স সার্ভিস তার অনানুষ্ঠানটি হ্যান্ডলিআইন্টেন্ট পদ্ধতিটি একটি পটভূমির থ্রেডে চালায়।
স্টিভি

দীর্ঘ চলমান ক্রিয়াকলাপগুলির জন্য আপনার একটি অ্যাসিঙ্কটাস্ক ব্যবহার করা উচিত নয়! গাইডলাইনস সর্বোচ্চ 2 থেকে 3 সেকেন্ড সুনির্দিষ্ট করে।
ডেজ

76

অন্য থ্রেডে নেটওয়ার্ক ক্রিয়া করুন

উদাহরণ স্বরূপ:

new Thread(new Runnable(){
    @Override
    public void run() {
        // Do network action in this function
    }
}).start();

এবং এটিকে AndroidManLive.xML এ যুক্ত করুন

<uses-permission android:name="android.permission.INTERNET"/>

5
তবে থ্রেডটি শেষ হয়ে গেলে আমরা কীভাবে এটি জানতে পারি যাতে আমরা ইউআই থ্রেডের পরবর্তী সেটগুলি সম্পাদন করতে পারি? অ্যাসিঙ্কটাস্ক এটি করার সুবিধা দেয়। রান্নেবল থ্রেড ব্যবহার করে কি একইভাবে করার উপায় আছে?
পীযূষ সনি

3
এটি আপনার কোডটি ধাপে ধাপে প্রক্রিয়া করবে, সুতরাং কোড শেষ হওয়ার পরে আপনাকে হ্যান্ডলারটি ইউআই থ্রেডে ফিরে ব্যবহার করতে হবে
henry4343

1
আপনি অ্যাসিঙ্ক টাস্ক বা উদ্দেশ্য পরিষেবাটি ব্যবহার করতে পারেন, কারণ এটি কর্মী থ্রেডে কার্যকর হয়।
চেতন চৌধারী

62

আপনি নিম্নলিখিত কোড ব্যবহার করে কঠোর মোডটি অক্ষম করুন:

if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = 
        new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}

এটি প্রস্তাবিত নয় : AsyncTaskইন্টারফেসটি ব্যবহার করুন ।

উভয় পদ্ধতির জন্য সম্পূর্ণ কোড


2
হ্যাঁ এএনআর ত্রুটি আসবে। মানে অ্যাপটি 5 সেকেন্ডে সাড়া দিচ্ছে না।
মুহাম্মদ মুবাশির

11
এটি একটি সত্যই খারাপ উত্তর। আপনার থ্রেডের নীতি পরিবর্তন করা উচিত নয় তবে আরও ভাল কোড লিখতে হবে: মূল থ্রেডে নেটওয়ার্ক অপারেশন করবেন না!
shkschneider

@ সন্দীপ আপনার এবং অন্যান্য দর্শকদের এটিও পড়তে হবে। stackoverflow.com/a/18335031/3470479
Prakhar1001

54

নেটওয়ার্ক-ভিত্তিক অপারেশনগুলি মূল থ্রেডে চালানো যায় না। আপনার বাচ্চাদের থ্রেডে সমস্ত নেটওয়ার্ক-ভিত্তিক কাজ পরিচালনা করা বা অ্যাসিঙ্কটাস্ক প্রয়োগ করা দরকার।

চাইল্ড থ্রেডে আপনি এভাবে কোনও টাস্ক চালাবেন:

new Thread(new Runnable(){
    @Override
    public void run() {
        try {
            // Your implementation goes here
        } 
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}).start();

বেনামে রান্নেবল সবচেয়ে ভাল উপায় নয়, যেহেতু এটি বন্ধক শ্রেণীর অন্তর্নিহিত রেফারেন্স রয়েছে এবং থ্রেডটি সম্পূর্ণ না হওয়া পর্যন্ত এটি জিসি এড হতে আটকাচ্ছে! এছাড়াও এই থ্রেডটি একই / অগ্রাধিকার ভিত্তিতে মূল / মার্কিন থ্রেড হিসাবে চলবে, যা জীবনচক্র পদ্ধতি এবং ইউআই ফ্রেমের হারের সাথে লড়াই করে!
ইউশা আলেয়ুব

49

আপনার কোড ভিতরে রাখুন:

new Thread(new Runnable(){
    @Override
    public void run() {
        try {
            // Your implementation
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}).start();

বা:

class DemoTask extends AsyncTask<Void, Void, Void> {

    protected Void doInBackground(Void... arg0) {
        //Your implementation
    }

    protected void onPostExecute(Void result) {
        // TODO: do something with the feed
    }
}

দ্বিতীয় একটি 11 এরও বেশি উপরে এপিআইয়ের জন্য সেরা হবে
রোহিত গোস্বামী

46

এটি অ্যান্ড্রয়েড 3.0.০ এবং তারপরেও ঘটে। অ্যান্ড্রয়েড 3.0.০ এবং তার থেকে উপরে, তারা নেটওয়ার্ক অপারেশনগুলি (ইন্টারনেট অ্যাক্সেস করে এমন ফাংশনগুলি) মূল থ্রেড / ইউআই থ্রেডে চালানো থেকে নিষিদ্ধ করেছে (আপনার তৈরিতে এবং ক্রিয়াকলাপে পুনরায় চালু পদ্ধতিতে কী উত্সাহিত করে)।

এটি নেটওয়ার্ক অপারেশনের জন্য পৃথক থ্রেড ব্যবহার করে উত্সাহিত করা। কীভাবে সঠিকভাবে নেটওয়ার্ক ক্রিয়াকলাপ সম্পাদন করা যায় সে সম্পর্কে আরও তথ্যের জন্য অ্যাসিঙ্কটাস্ক দেখুন ।


46

অ্যান্ড্রয়েড টীকাগুলি ব্যবহার করা একটি বিকল্প। এটি আপনাকে ব্যাকগ্রাউন্ড থ্রেডে কোনও পদ্ধতি চালানোর অনুমতি দেয়:

// normal method
private void normal() {
    doSomething(); // do something in background
}

@Background
protected void doSomething() 
    // run your networking code here
}

দ্রষ্টব্য, যদিও এটি সরলতা এবং পাঠযোগ্যতার সুবিধাগুলি সরবরাহ করে তবে এর অসুবিধাগুলি রয়েছে।


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

43

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

AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {

    @Override
    public void onStart() {
        // Called before a request is started
    }

    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] response) {
        // Called when response HTTP status is "200 OK"
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
        // Called when response HTTP status is "4XX" (for example, 401, 403, 404)
    }

    @Override
    public void onRetry(int retryNo) {
        // Called when request is retried
    }
});

42

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

এই সব জিনিস প্রক্রিয়া সহজ জন্য, Android বিভিন্ন উপায়ে, মত প্রদান করে AsyncTask, AsyncTaskLoader, CursorLoaderবা IntentService। সুতরাং আপনি আপনার প্রয়োজনীয়তা অনুসারে এর যে কোনওটি ব্যবহার করতে পারেন।


40

স্পেকটমের শীর্ষ উত্তর সঠিকভাবে কাজ করে।

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

RSSFeed feed = new RetreiveFeedTask().execute(urlToRssFeed).get();

(তার উদাহরণ থেকে।)


5
ব্যবহার get() করা একটি খারাপ ধারণা ... এটি AsyncTask আবার "সিঙ্ক" করে তোলে
সেলভিন

এর থেকে আরও ভাল উপায় কি আছে? @ সেলভিন
সিভ্যাগ 1

2
আমি মনে করি আপনি ফলাফলটি সম্পর্কে মূল থ্রেডটি তথ্য জানাতে পারেন example উদাহরণস্বরূপ, ফলাফল সহ মূল থ্রেডে একটি সম্প্রচার পাঠান।
চাইন গ্যারি

32

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

ত্রুটিটি এসডিকে সতর্কতা!


28

আমার জন্য এটি ছিল:

<uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="10" />

আমি আমার অ্যাপটিতে যে ডিভাইসটি পরীক্ষা করছি তার ডিভাইসটি ছিল 4.1.2 যা এসডিকে সংস্করণ 16!

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

এছাড়াও, অন্যরা যেমন বলেছে, ইন্টারনেট অ্যাক্সেসের সঠিক অনুমতিগুলি অন্তর্ভুক্ত করুন:

<uses-permission android:name="android.permission.INTERNET"/>

11
আপনি এখানে কী করছেন তা আমি আপনাকে ব্যাখ্যা করতে পারি: NetworkOnMainThreadExceptionঅভিভাবক যা আপনাকে বলছেন: নিজের পায়ে গুলি করবেন না ... আপনার সমাধানটি হ'ল: যখন কোনও অভিভাবক ছিল না অতীতে ফিরে যাই - এখন আমি আমার দিকে গুলি করতে পারি অবাধে
পদক্ষেপ

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

25

আপনার ক্রিয়াকলাপ এ এটি ব্যবহার করুন

    btnsub.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub

                    //Initialize soap request + add parameters
                    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME1);

                    //Use this to add parameters
                    request.addProperty("pincode", txtpincode.getText().toString());
                    request.addProperty("bg", bloodgroup.getSelectedItem().toString());

                    //Declare the version of the SOAP request
                    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);

                    envelope.setOutputSoapObject(request);
                    envelope.dotNet = true;

                    try {
                        HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

                        //this is the actual part that will call the webservice
                        androidHttpTransport.call(SOAP_ACTION1, envelope);

                        // Get the SoapResult from the envelope body.
                        SoapObject result = (SoapObject) envelope.getResponse();
                        Log.e("result data", "data" + result);
                        SoapObject root = (SoapObject) result.getProperty(0);
                        // SoapObject s_deals = (SoapObject) root.getProperty(0);
                        // SoapObject s_deals_1 = (SoapObject) s_deals.getProperty(0);
                        //

                        System.out.println("********Count : " + root.getPropertyCount());

                        value = new ArrayList<Detailinfo>();

                        for (int i = 0; i < root.getPropertyCount(); i++) {
                            SoapObject s_deals = (SoapObject) root.getProperty(i);
                            Detailinfo info = new Detailinfo();

                            info.setFirstName(s_deals.getProperty("Firstname").toString());
                            info.setLastName(s_deals.getProperty("Lastname").toString());
                            info.setDOB(s_deals.getProperty("DOB").toString());
                            info.setGender(s_deals.getProperty("Gender").toString());
                            info.setAddress(s_deals.getProperty("Address").toString());
                            info.setCity(s_deals.getProperty("City").toString());
                            info.setState(s_deals.getProperty("State").toString());
                            info.setPinecode(s_deals.getProperty("Pinecode").toString());
                            info.setMobile(s_deals.getProperty("Mobile").toString());
                            info.setEmail(s_deals.getProperty("Email").toString());
                            info.setBloodgroup(s_deals.getProperty("Bloodgroup").toString());
                            info.setAdddate(s_deals.getProperty("Adddate").toString());
                            info.setWaight(s_deals.getProperty("waight").toString());
                            value.add(info);
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    Intent intent = new Intent(getApplicationContext(), ComposeMail.class);
                    //intent.putParcelableArrayListExtra("valuesList", value);

                    startActivity(intent);
                }
            }).start();
        }
    });

23

স্পষ্টভাবে কিছু বানান করতে:

মূল থ্রেডটি মূলত ইউআই থ্রেড।

সুতরাং বলছেন যে আপনি মূল থ্রেডে নেটওয়ার্কিং অপারেশন করতে পারবেন না তার অর্থ আপনি ইউআই থ্রেডে নেটওয়ার্কিং অপারেশন করতে পারবেন না , যার অর্থ আপনি কোনও *runOnUiThread(new Runnable() { ... }*ব্লকে নেটওয়ার্কিং অপারেশন করতে পারবেন না অন্য কোনও থ্রেডের ভিতরে কোনও ।

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


22

মূল থ্রেডে সঞ্চালিত ভারী কোনও কাজের কারণে এই ব্যতিক্রম ঘটায় যদি সেই কার্য সম্পাদনকারী টাস্কটি খুব বেশি সময় নেয় ।

এটি এড়াতে, আমরা থ্রেড বা এক্সিকিউটার ব্যবহার করে এটি পরিচালনা করতে পারি

Executors.newSingleThreadExecutor().submit(new Runnable() {
    @Override
    public void run() {
        // You can perform your task here.
    }
});

18

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

আমি নেটওয়ার্ক ক্রিয়াকলাপ সম্পাদন করার জন্য বেশ কয়েকটি ব্যবহারের কেস এবং প্রতিটিটির জন্য একটি সমাধান বা দুটি coverেকে দেব ।

HTTP- র উপরে বিশ্রাম দিন

সাধারণত জসন, এক্সএমএল বা অন্য কিছু হতে পারে

সম্পূর্ণ API অ্যাক্সেস

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

http://api.example.com/stocks                       //ResponseWrapper<String> object containing a list of Srings with ticker symbols
http://api.example.com/stocks/$symbol               //Stock object
http://api.example.com/stocks/$symbol/prices        //PriceHistory<Stock> object
http://api.example.com/currencies                   //ResponseWrapper<String> object containing a list of currency abbreviation
http://api.example.com/currencies/$currency         //Currency object
http://api.example.com/currencies/$id1/values/$id2  //PriceHistory<Currency> object comparing the prices of the first currency (id1) to the second (id2)

স্কয়ার থেকে retrofit

এটি একাধিক এন্ডপয়েন্টস সহ একটি API এর জন্য দুর্দান্ত পছন্দ এবং আপনাকে আয়ন বা ভলির মতো অন্যান্য লাইব্রেরির মতো আলাদা আলাদাভাবে কোড করার পরিবর্তে আরএসটি শেষ পয়েন্টগুলি ঘোষণা করতে দেয়। (ওয়েবসাইট: http://square.github.io/retrofit/ )

আপনি এটি ফিনান্সিয়াস এপিআই দিয়ে কীভাবে ব্যবহার করবেন?

build.gradle

আপনার মডিউল স্তরের বিড.gradle এ এই লাইনগুলি যুক্ত করুন:

implementation 'com.squareup.retrofit2:retrofit:2.3.0' //retrofit library, current as of September 21, 2017
implementation 'com.squareup.retrofit2:converter-gson:2.3.0' //gson serialization and deserialization support for retrofit, version must match retrofit version

FinancesApi.java

public interface FinancesApi {
    @GET("stocks")
    Call<ResponseWrapper<String>> listStocks();
    @GET("stocks/{symbol}")
    Call<Stock> getStock(@Path("symbol")String tickerSymbol);
    @GET("stocks/{symbol}/prices")
    Call<PriceHistory<Stock>> getPriceHistory(@Path("symbol")String tickerSymbol);

    @GET("currencies")
    Call<ResponseWrapper<String>> listCurrencies();
    @GET("currencies/{symbol}")
    Call<Currency> getCurrency(@Path("symbol")String currencySymbol);
    @GET("currencies/{symbol}/values/{compare_symbol}")
    Call<PriceHistory<Currency>> getComparativeHistory(@Path("symbol")String currency, @Path("compare_symbol")String currencyToPriceAgainst);
}

FinancesApiBuilder

public class FinancesApiBuilder {
    public static FinancesApi build(String baseUrl){
        return new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
                    .create(FinancesApi.class);
    }
}

ফিনান্সফ্র্যাগমেন্ট স্নিপেট

FinancesApi api = FinancesApiBuilder.build("http://api.example.com/"); //trailing '/' required for predictable behavior
api.getStock("INTC").enqueue(new Callback<Stock>(){
    @Override
    public void onResponse(Call<Stock> stockCall, Response<Stock> stockResponse){
        Stock stock = stockCall.body();
        //do something with the stock
    }
    @Override
    public void onResponse(Call<Stock> stockCall, Throwable t){
        //something bad happened
    }
}

যদি আপনার এপিআই-তে কোনও API কী বা অন্য কোনও শিরোনামের মতো ব্যবহারকারী টোকেন ইত্যাদি প্রেরণের প্রয়োজন হয় তবে retrofit এটিকে সহজ করে তোলে (বিশদগুলির জন্য এই দুর্দান্ত উত্তরটি দেখুন: https://stackoverflow.com/a/42899766/1024412 )।

একমাত্র রিস্টের এপিআই অ্যাক্সেস

ধরা যাক আপনি একটি "মেজাজ আবহাওয়া" অ্যাপ্লিকেশন তৈরি করছেন যা ব্যবহারকারীদের জিপিএস অবস্থানের সন্ধান করে এবং সেই অঞ্চলের বর্তমান তাপমাত্রা পরীক্ষা করে এবং তাদের মেজাজটি জানায়। এই ধরণের অ্যাপ্লিকেশনটির API এন্ডপয়েন্টগুলি ঘোষণা করার দরকার নেই; এটিতে কেবল একটি এপিআই এর শেষ পয়েন্ট অ্যাক্সেস করতে সক্ষম হওয়া প্রয়োজন।

স্থূলাণু

এই ধরণের অ্যাক্সেসের জন্য এটি একটি দুর্দান্ত পাঠাগার।

দয়া করে এমএসমিলুর দুর্দান্ত উত্তরটি পড়ুন ( https://stackoverflow.com/a/28559884/1024412 )

HTTP- র মাধ্যমে চিত্রগুলি লোড করুন

নিক্ষেপ

ভ্যালি আরএসটি এপিআই-র জন্যও ব্যবহার করা যেতে পারে তবে আরও জটিল সেটআপের কারণে আমি উপরের স্কোয়ার থেকে রেট্রোফিট ব্যবহার করতে পছন্দ করি ( http://square.github.io/retrofit/ )

ধরা যাক আপনি একটি সামাজিক নেটওয়ার্কিং অ্যাপ তৈরি করছেন এবং বন্ধুদের প্রোফাইল ছবি লোড করতে চান।

build.gradle

আপনার মডিউল স্তরের বিড.gradle এ এই লাইন যুক্ত করুন:

implementation 'com.android.volley:volley:1.0.0'

ImageFetch.java

ভলির রেট্রোফিটের চেয়ে বেশি সেটআপ প্রয়োজন। একটি রিকুয়েস্টকুই, একটি ইমেজলোডার এবং একটি চিত্রক্যাচ সেটআপ করার জন্য আপনাকে এই জাতীয় শ্রেণি তৈরি করতে হবে তবে এটি খুব খারাপ নয়:

public class ImageFetch {
    private static ImageLoader imageLoader = null;
    private static RequestQueue imageQueue = null;

    public static ImageLoader getImageLoader(Context ctx){
        if(imageLoader == null){
            if(imageQueue == null){
                imageQueue = Volley.newRequestQueue(ctx.getApplicationContext());
            }
            imageLoader = new ImageLoader(imageQueue, new ImageLoader.ImageCache() {
                Map<String, Bitmap> cache = new HashMap<String, Bitmap>();
                @Override
                public Bitmap getBitmap(String url) {
                    return cache.get(url);
                }
                @Override
                public void putBitmap(String url, Bitmap bitmap) {
                    cache.put(url, bitmap);
                }
            });
        }
        return imageLoader;
    }
}

user_view_dialog.xml

একটি চিত্র যুক্ত করতে আপনার লেআউট এক্সএমএল ফাইলটিতে নিম্নলিখিতগুলি যুক্ত করুন:

<com.android.volley.toolbox.NetworkImageView
    android:id="@+id/profile_picture"
    android:layout_width="32dp"
    android:layout_height="32dp"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    app:srcCompat="@android:drawable/spinner_background"/>

UserViewDialog.java

অনক্রিট পদ্ধতিতে (খণ্ড, ক্রিয়াকলাপ) বা কনস্ট্রাক্টর (ডায়ালগ) -এ নিম্নলিখিত কোড যুক্ত করুন:

NetworkImageView profilePicture = view.findViewById(R.id.profile_picture);
profilePicture.setImageUrl("http://example.com/users/images/profile.jpg", ImageFetch.getImageLoader(getContext());

পিকাসো

স্কয়ার থেকে আরও একটি দুর্দান্ত গ্রন্থাগার। কয়েকটি দুর্দান্ত উদাহরণের জন্য দয়া করে সাইটটি দেখুন: http://square.github.io/picasso/


16

সহজ কথায়,

ইউআই থ্রেডে নেট ওয়ার্ক করবেন না

উদাহরণস্বরূপ, আপনি যদি এইচটিটিপি অনুরোধ করেন তবে এটি একটি নেটওয়ার্ক অ্যাকশন।

সমাধান:

  1. আপনাকে একটি নতুন থ্রেড তৈরি করতে হবে
  2. অথবা অ্যাসিঙ্কটাস্ক ক্লাস ব্যবহার করুন

ওয়ে:

আপনার সমস্ত কাজ ভিতরে রাখুন

  1. run() নতুন থ্রেডের পদ্ধতি
  2. বা doInBackground() অ্যাসিঙ্কটাস্ক ক্লাসের পদ্ধতি।

কিন্তু:

আপনি যখন নেটওয়ার্ক প্রতিক্রিয়া থেকে কিছু পান এবং এটি আপনার দৃষ্টিতে (টেক্সটভিউতে প্রদর্শন প্রতিক্রিয়া বার্তার মতো) দেখাতে চান, আপনাকে আবার ইউআই থ্রেডে ফিরে আসতে হবে

আপনি যদি এটি না করেন তবে আপনি পাবেন ViewRootImpl$CalledFromWrongThreadException

কিভাবে?

  1. অ্যাসিঙ্কটাস্ক ব্যবহার করার সময়, onPostExecute()পদ্ধতি থেকে দর্শন আপডেট করুন
  2. অথবাrunOnUiThread() পদ্ধতির অভ্যন্তরে কল পদ্ধতি এবং আপডেট ভিউ run()

12

আপনি আপনার কোডের একটি অংশ অন্য থ্রেডে অফলোড করতে main threadএবং এএনআর , নেটওয়ার্কঅনমেনথ্রেডএক্সসেপশন , অবৈধ স্টেটএক্সসেপশন এড়াতে সক্ষম হবেন (যেমন মূল থ্রেডে ডেটাবেস অ্যাক্সেস করতে পারবেন না কারণ এটি দীর্ঘ সময় ধরে ইউআই লক করতে পারে)।

কিছু পন্থা রয়েছে যা আপনার চয়ন করা উচিত পরিস্থিতির উপর নির্ভর করে

জাভা থ্রেড বা অ্যান্ড্রয়েড হ্যান্ডলারথ্রেড

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

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

AsyncTask

অ্যাসিঙ্কটাস্ক থ্রেড এবং হ্যান্ডলারের আশেপাশে একটি সহায়ক শ্রেণি হিসাবে ডিজাইন করা হয়েছে এবং এটি জেনেরিক থ্রেডিং ফ্রেমওয়ার্ক গঠন করে না। অ্যাসিঙ্কটাস্কগুলি আদর্শভাবে সংক্ষিপ্ত ক্রিয়াকলাপের জন্য ব্যবহার করা উচিত (সর্বাধিক কয়েক সেকেন্ড) threads যদি আপনাকে দীর্ঘ সময় ধরে থ্রেড চলতে থাকে তবে এটি java.util.concurrent প্যাকেজ দ্বারা সরবরাহিত বিভিন্ন API ব্যবহার করার পরামর্শ দেওয়া হয় is এক্সিকিউটার , থ্রেডপুলএক্সেকিউটার এবং ফিউচারটাস্ক

থ্রেড পুল বাস্তবায়ন ThreadPoolExecutor , ScheduledThreadPoolExecutor ...

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

নির্ধারিত থ্রেডপুলএক্সেকটর - একটি শ্রেণি যা থ্রেডপুলএক্সেকিউটারকে প্রসারিত করে। এটি কোনও নির্দিষ্ট বিলম্বের পরে বা পর্যায়ক্রমে কার্যগুলি নির্ধারণ করতে পারে।

FutureTask

ফিউচারটাস্ক অ্যাসিনক্রোনাস প্রসেসিং সম্পাদন করে, তবে, ফলাফলটি এখনও প্রস্তুত না হলে বা প্রক্রিয়াজাতকরণ শেষ না হলে, গেট কল করুন () থ্রেডটিকে ব্লক করে দেবে

AsyncTaskLoaders

অ্যাসিঙ্কটাস্কলয়েডাররা AsyncTask সহজাত অনেকগুলি সমস্যা সমাধান করায়

IntentService

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

JobScheduler

কার্যকরভাবে, আপনাকে একটি পরিষেবা তৈরি করতে হবে এবং JobInfo.Builder ব্যবহার করে একটি চাকরী তৈরি করতে হবে যা পরিষেবাটি কখন চালাবে তার জন্য আপনার মানদণ্ড নির্দিষ্ট করে।

RxJava

পর্যবেক্ষণযোগ্য ক্রমগুলি ব্যবহার করে অ্যাসিনক্রোনাস এবং ইভেন্ট-ভিত্তিক প্রোগ্রামগুলি রচনা করার জন্য লাইব্রেরি।

কর্টিনস (কোটলিন)

এটির মূল বক্তব্যটি, এটি এ্যাসক্রোনাস কোডটিকে অনেকটা সিঙ্ক্রোনাসের মতো দেখায়

এখানে , এখানে , এখানে , এখানে আরও পড়ুন


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

দয়া করে পদ্ধতিটি দেখুন: asyncTask.executeOnExecutor (AsyncTask.THREAD_POOL_EXECUTOR, প্যারাম); আপনার কাজটি এক সাথে চালাতে
yoAlex5

10

যদিও উপরে একটি বিশাল সমাধান পুল রয়েছে, তবে কেউ উল্লেখ করেছেন com.koushikdutta.ion: https://github.com/koush/ion

এটি অবিচ্ছিন্ন এবং ব্যবহার করা খুব সহজ :

Ion.with(context)
.load("http://example.com/thing.json")
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
   @Override
    public void onCompleted(Exception e, JsonObject result) {
        // do stuff with the result or error
    }
});

10

নতুন Threadএবং অ্যাসিঙ্কটাস্ক সমাধানগুলি ইতিমধ্যে ব্যাখ্যা করা হয়েছে।

AsyncTaskসংক্ষিপ্ত ক্রিয়াকলাপের জন্য আদর্শভাবে ব্যবহার করা উচিত। Threadঅ্যান্ড্রয়েডের জন্য সাধারণ পছন্দনীয় নয়।

বিকল্প সলিউশন ব্যবহার কটাক্ষপাত আছে HandlerThread এবং হ্যান্ডলার

HandlerThread

একটি লুপ রয়েছে এমন একটি নতুন থ্রেড শুরু করার জন্য হ্যান্ডি ক্লাস। লুপারটি হ্যান্ডলার ক্লাস তৈরি করতে ব্যবহৃত হতে পারে। নোট যে start()এখনও কল করা উচিত।

হ্যান্ডলার সঠিক নয়:

একটি হ্যান্ডলার আপনাকে কোনও থ্রেডের মেসেজকুইয়ের সাথে সম্পর্কিত বার্তা এবং চলমানযোগ্য বস্তু প্রেরণ এবং প্রক্রিয়া করার অনুমতি দেয়। প্রতিটি হ্যান্ডলারের উদাহরণটি একক থ্রেড এবং সেই থ্রেডের বার্তার সারিটির সাথে সম্পর্কিত। যখন আপনি একটি নতুন হ্যান্ডলার তৈরি করেন, এটি যে থ্রেডটি তৈরি করছে তার থ্রেড / বার্তা সারিতে আবদ্ধ - সেদিক থেকে এটি বার্তাগুলি এবং রানবেলগুলি সেই বার্তার কাতারে পৌঁছে দেবে এবং বার্তাটি বেরিয়ে আসার সাথে সাথে তাদের সম্পাদন করবে কিউ.

সমাধান:

  1. সৃষ্টি HandlerThread

  2. ফোন start()করুনHandlerThread

  3. থেকে Handlerপেয়ে তৈরি করুনLooperHanlerThread

  4. আপনার নেটওয়ার্ক অপারেশন সম্পর্কিত কোড Runnableঅবজেক্টে এম্বেড করুন

  5. Runnableটাস্ক জমা দিনHandler

নমুনা কোড স্নিপেট, কোন ঠিকানা NetworkOnMainThreadException

HandlerThread handlerThread = new HandlerThread("URLConnection");
handlerThread.start();
handler mainHandler = new Handler(handlerThread.getLooper());

Runnable myRunnable = new Runnable() {
    @Override
    public void run() {
        try {
            Log.d("Ravi", "Before IO call");
            URL page = new URL("http://www.google.com");
            StringBuffer text = new StringBuffer();
            HttpURLConnection conn = (HttpURLConnection) page.openConnection();
            conn.connect();
            InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
            BufferedReader buff = new BufferedReader(in);
            String line;
            while ( (line =  buff.readLine()) != null) {
                text.append(line + "\n");
            }
            Log.d("Ravi", "After IO call");
            Log.d("Ravi",text.toString());

        }catch( Exception err){
            err.printStackTrace();
        }
    }
};
mainHandler.post(myRunnable);

এই পদ্ধতির ব্যবহারের পেশাদার:

  1. Thread/AsyncTaskপ্রতিটি নেটওয়ার্ক অপারেশনের জন্য নতুন তৈরি করা ব্যয়বহুল। Thread/AsyncTaskধ্বংস হয়ে যাবে এবং পরবর্তী নেটওয়ার্ক অপারেশনের জন্য পুনরায় সৃষ্টি করেছেন। তবে Handlerএবং HandlerThreadপদ্ধতির সাথে, আপনি অনেকগুলি নেটওয়ার্ক অপারেশন (চলমান কাজ হিসাবে) HandlerThreadব্যবহার করে একা জমা দিতে পারেন Handler

8

RxAndroidএই সমস্যার আর একটি ভাল বিকল্প এবং এটি আমাদের থ্রেড তৈরির ঝামেলা থেকে বাঁচায় এবং তারপরে অ্যান্ড্রয়েড ইউআই থ্রেডে ফলাফল পোস্ট করুন। আমাদের কেবল থ্রেডগুলি নির্দিষ্ট করতে হবে যার উপর কোন কাজগুলি সম্পাদন করা দরকার এবং অভ্যন্তরীণভাবে সবকিছু পরিচালনা করা হয়।

Observable<List<String>> musicShowsObservable = Observable.fromCallable(new Callable<List<String>>() { 

  @Override 
  public List<String> call() { 
    return mRestClient.getFavoriteMusicShows(); 
  }
});

mMusicShowSubscription = musicShowsObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<String>>() {

    @Override 
    public void onCompleted() { }

    @Override 
    public void onError(Throwable e) { }

    @Override 
    public void onNext(List<String> musicShows){
        listMusicShows(musicShows);
    }
});
  1. নির্দিষ্ট করে (Schedulers.io()), RxAndroid getFavoriteMusicShows() একটি আলাদা থ্রেডে চলবে on

  2. ব্যবহার করে AndroidSchedulers.mainThread()আমরা এই পর্যবেক্ষণযোগ্যটি ইউআই থ্রেডে পর্যবেক্ষণ করতে চাই, অর্থাৎ আমরা আমাদের onNext()কলব্যাকটি ইউআই থ্রেডে কল করতে চাই


8

প্রধান থ্রেড হ'ল ইউআই থ্রেড এবং আপনি মূল থ্রেডে কোনও ক্রিয়াকলাপ করতে পারবেন না যা ব্যবহারকারীর মিথস্ক্রিয়াকে অবরুদ্ধ করতে পারে। আপনি এটি দুটি উপায়ে সমাধান করতে পারেন:

মূল থ্রেডের মতো টাস্কটি করতে বাধ্য করুন

StrictMode.ThreadPolicy threadPolicy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(threadPolicy);

অথবা একটি সাধারণ হ্যান্ডলার তৈরি করুন এবং আপনি চাইলে মূল থ্রেড আপডেট করুন।

Runnable runnable;
Handler newHandler;

newHandler = new Handler();
runnable = new Runnable() {
    @Override
    public void run() {
         try {
            //update UI
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
};
newHandler.post(runnable);

এবং থ্রেড ব্যবহার বন্ধ করতে:

newHandler.removeCallbacks(runnable);

আরও তথ্যের জন্য এটি পরীক্ষা করে দেখুন: বেদাহীন থ্রেডিং


ধন্যবাদ. অনক্রয়েটে প্রথম ক্রিয়া হিসাবে যুক্ত করার সময় সংস্করণ 1 সহায়তা করে।
ইঙ্গো

7

এইটা কাজ করে. ডক্টর লুইজির উত্তরটি কিছুটা সহজ করে তুলেছে।

new Thread() {
    @Override
    public void run() {
        try {
            //Your code goes here
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}.start();

7

Android এ, নেটওয়ার্ক অপারেশনগুলি মূল থ্রেডে চালানো যায় না। নেটওয়ার্ক ক্রিয়াকলাপ করতে আপনি থ্রেড, অ্যাসিঙ্কটাস্ক (স্বল্প-চলমান কার্য), পরিষেবা (দীর্ঘ-চলমান কার্য) ব্যবহার করতে পারেন।


7

মূল (ইউআই) থ্রেড থেকে নেটওয়ার্ক সংস্থান অ্যাক্সেস করা এই ব্যতিক্রম ঘটায়। এই সমস্যাটি এড়াতে একটি নেটওয়ার্ক সংস্থান অ্যাক্সেসের জন্য একটি পৃথক থ্রেড বা অ্যাসিঙ্কটাস্ক ব্যবহার করুন।

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