Java 如何修复';android.os.NetworkOnMainThreadException';?

Java 如何修复';android.os.NetworkOnMainThreadException';?,java,android,android-networking,networkonmainthread,Java,Android,Android Networking,Networkonmainthread,我在为RssReader运行Android项目时出错 代码: 并显示以下错误: android.os.NetworkOnMainThreadException 如何解决此问题?您无法在上的UI线程上执行网络。从技术上讲,这在早期版本的Android上是可能的,但这是一个非常糟糕的主意,因为它会导致你的应用程序停止响应,并可能导致操作系统因为你的应用程序表现不好而杀死你的应用程序。您需要运行后台进程或使用AsyncTask在后台线程上执行网络事务 Android开发者网站上有一篇关于这方面的文章

我在为RssReader运行Android项目时出错

代码:

并显示以下错误:

android.os.NetworkOnMainThreadException

如何解决此问题?

您无法在上的UI线程上执行网络。从技术上讲,这在早期版本的Android上是可能的,但这是一个非常糟糕的主意,因为它会导致你的应用程序停止响应,并可能导致操作系统因为你的应用程序表现不好而杀死你的应用程序。您需要运行后台进程或使用AsyncTask在后台线程上执行网络事务


Android开发者网站上有一篇关于这方面的文章,这是一篇很好的介绍,它将为您提供比这里实际提供的更深入的答案。

注意:AsyncTask在API级别30中被弃用。

当应用程序尝试在其主线程上执行网络操作时,会引发此异常。在以下位置运行代码:

不要忘记将此添加到
AndroidManifest.xml
文件:

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

您几乎应该始终在线程上或作为异步任务运行网络操作。

但是,如果您愿意接受后果,则可以删除此限制并覆盖默认行为

加:

在你们班上

在android manifest.xml文件中添加此权限:

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

后果:

您的应用程序(在互联网连接不稳定的区域)将变得无响应和锁定,用户感觉到速度缓慢,必须进行强制杀戮,并且您有可能让活动管理器杀掉您的应用程序并告诉用户应用程序已停止

Android提供了一些关于良好编程实践的好提示,以设计响应能力:
您可以使用以下代码禁用严格模式:

if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = 
        new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}
不建议这样做:使用
异步任务
界面


这个问题有两种解决方案

1) 不要在主UI线程中编写网络调用,使用异步任务

2) 在setContentView(R.layout.activity_main)之后,将以下代码写入MainActivity文件

下面是导入语句到java文件中

import android.os.StrictMode;

我用一个新的
线程解决了这个问题

Thread thread = new Thread(new Runnable() {

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

thread.start(); 
上衣很好用

如果您是以内联方式编写
AsyncTask
而不是作为类进行扩展,并且在此基础上,如果需要从
AsyncTask
中获取响应,可以使用下面的
get()
方法

RSSFeed feed = new RetreiveFeedTask().execute(urlToRssFeed).get();
(来自他的例子。)

  • 不要使用strictMode(仅在调试模式下)
  • 不要更改SDK版本
  • 不要使用单独的螺纹
  • 使用服务或异步任务

    另见问题:


    这在Android 3.0及以上版本中发生。从Android 3.0和更高版本开始,他们限制使用网络操作(访问互联网的功能)在主线程/UI线程中运行(从活动中的on create和on resume方法生成)

    这是为了鼓励使用单独的线程进行网络操作。有关如何以正确的方式执行网络活动的更多详细信息,请参阅。

    对我来说,这是:

    <uses-sdk
            android:minSdkVersion="8"
            android:targetSdkVersion="10" />
    
    
    
    我测试应用程序的设备是4.1.2,是SDK版本16

    确保目标版本与Android目标库相同。如果不确定目标库是什么,请右键单击项目->构建路径->Android,它应该是勾选的目标库

    此外,如其他人所述,包括访问Internet的正确权限:

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

    在另一个线程上执行网络操作

    例如:

    并将其添加到AndroidManifest.xml

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

    您不应该在主线程(UI线程)上执行任何耗时的任务,如任何网络操作、文件I/O或SQLite数据库操作。因此,对于这种操作,您应该创建一个工作线程,但问题是您不能直接从工作线程执行任何与UI相关的操作。为此,您必须使用
    处理程序
    并传递
    消息


    为了简化所有这些事情,Android提供了各种方式,如
    AsyncTask
    AsyncTaskLoader
    CursorLoader
    IntentService
    。因此,您可以根据需要使用其中任何一个。

    基于网络的操作不能在主线程上运行。您需要在子线程上运行所有基于网络的任务或实现AsyncTask

    以下是在子线程中运行任务的方式:

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

    公认的答案有一些明显的负面影响。除非您真的知道自己在做什么,否则不建议使用AsyncTask进行联网。一些不利因素包括:

    • 创建为非静态内部类的AsyncTask具有对封闭活动对象、其上下文和该活动创建的整个视图层次结构的隐式引用。此引用防止在AsyncTask的后台工作完成之前对活动进行垃圾收集。如果用户的连接速度慢,和/或下载量大,这些短期内存泄漏可能会成为一个问题-例如,如果方向多次更改(并且您没有取消正在执行的任务),或者用户导航离开活动
    • AsyncTask具有不同的执行特征,这取决于它在哪个平台上执行:在API级别4之前,AsyncTask在单个后台线程上串行执行;从API级别4到API级别10,异步任务在多达128个线程的池中执行;从API级别11开始,AsyncTask在单个后台线程上串行执行(除非使用重载的
      executeOnExecutor
      方法并提供备用执行器)。在ICS上串行运行时工作正常的代码在Gin上并发执行时可能会中断
      RSSFeed feed = new RetreiveFeedTask().execute(urlToRssFeed).get();
      
      <uses-sdk
              android:minSdkVersion="8"
              android:targetSdkVersion="10" />
      
      <uses-permission android:name="android.permission.INTERNET"/>
      
      new Thread(new Runnable(){
          @Override
          public void run() {
              // Do network action in this function
          }
      }).start();
      
      <uses-permission android:name="android.permission.INTERNET"/>
      
      new Thread(new Runnable(){
          @Override
          public void run() {
              try {
                  // Your implementation goes here
              } 
              catch (Exception ex) {
                  ex.printStackTrace();
              }
          }
      }).start();
      
      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);
              }
          }
      }
      
      <service
              android:name=".DownloadIntentService"
              android:exported="false"/>
      
      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);
      
      @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);
      }
      
          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();
              }
          });
      
      // normal method
      private void normal() {
          doSomething(); // do something in background
      }
      
      @Background
      protected void doSomething() 
          // run your networking code here
      }
      
      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
          }
      });
      
      Executors.newSingleThreadExecutor().submit(new Runnable() {
          @Override
          public void run() {
              // You can perform your task here.
          }
      });
      
      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
          }
      }
      
      new Thread() {
          @Override
          public void run() {
              try {
                  //Your code goes here
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      }.start();
      
      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
          }
      });
      
      String getUrl() {
          return "SomeUrl";
      }
      
      private Object makeCallParseResponse(String url) {
          return null;
          //
      }
      
      private void processResponse(Object o) {
      
      }
      
      rx.Observable.defer(new Func0<rx.Observable<String>>() {
          @Override
          public rx.Observable<String> call() {
              return rx.Observable.just(getUrl());
          }
      })
          .subscribeOn(Schedulers.io())
          .observeOn(Schedulers.io())
          .map(new Func1<String, Object>() {
              @Override
              public Object call(final String s) {
                  return makeCallParseResponse(s);
              }
          })
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe(new Action1<Object>() {
              @Override
              public void call(Object o) {
                   processResponse(o);
              }
          },
          new Action1<Throwable>() {
              @Override
              public void call(Throwable throwable) {
                  // Process error here, it will be posted on
                  // the main thread
              }
          });
      
         compile 'io.reactivex:rxjava:1.1.5'
         compile 'io.reactivex:rxandroid:1.2.0'
      
      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);
      
      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);
          }
      });
      
      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);
      
      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)
      
      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
      
      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);
      }
      
      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
          }
      }
      
      implementation 'com.android.volley:volley:1.0.0'
      
      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;
          }
      }
      
      <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"/>
      
      NetworkImageView profilePicture = view.findViewById(R.id.profile_picture);
      profilePicture.setImageUrl("http://example.com/users/images/profile.jpg", ImageFetch.getImageLoader(getContext());