我在运行RssReader的Android项目时出错。

代码:

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

如何解决此问题?


当前回答

不允许在Android上的UI线程上实现网络操作。您将不得不使用AsyncTask类来执行与网络相关的操作,如发送API请求、从URL下载图像等,并使用AsyncTask的回调方法,您可以在onPostExecute中获得结果,您将处于UI线程中,您可以使用web服务或类似的数据填充UI。

示例:假设您想从URL下载图像:https://www.samplewebsite.com/sampleimage.jpg

使用AsyncTask的解决方案:分别为。

    public class MyDownloader extends AsyncTask<String,Void,Bitmap>
    {
        @Override
        protected void onPreExecute() {
            // Show progress dialog
            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            //Populate Ui
            super.onPostExecute(bitmap);
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            // Open URL connection read bitmaps and return form here
            return result;
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            // Show progress update
            super.onProgressUpdate(values);
        }


    }
}

注意:不要忘记在Android清单文件中添加Internet权限。它会像一个魅力一样发挥作用。:)

其他回答

这是可行的。我只是让鲁伊吉医生的回答简单一点。

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

您可以将代码的一部分移动到另一个线程中以卸载主线程,并避免获得ANR、NetworkOnMainThreadException、IllegalStateException(例如,无法访问主线程上的数据库,因为它可能会长时间锁定UI)。

你应该根据情况选择一些方法

Java线程或Android HandlerThread:

Java线程只能一次性使用,并在执行其运行方法后死亡。HandlerThread是一个方便的类,用于启动具有looper的新线程。

AsyncTask(API级别30中已弃用)

AsyncTask被设计为围绕线程和处理程序的帮助类,不构成通用线程框架。AsyncTasks最好用于短操作(最多几秒钟)。如果需要让线程长时间运行,强烈建议您使用java.util.concurrent包提供的各种API,如Executor、ThreadPoolExecutor和FutureTask。

由于主线程独占UI组件,因此不可能访问某些视图,这就是为什么Handler会出手相助的原因

[执行器框架]

实现ExecutorService的ThreadPoolExecutor类,该类可以对线程池进行精细控制(例如,核心池大小、最大池大小、保活时间等)ScheduledThreadPoolExecutor-一个扩展ThreadPoolExecuto的类。它可以在给定延迟后或周期性地安排任务。

未来任务

FutureTask执行异步处理,但是,如果结果尚未就绪或处理尚未完成,则调用get()将阻塞线程

异步任务加载器

AsyncTaskLoader,因为它们解决了AsyncTask固有的许多问题

Intent服务

这是Android上长期运行处理的事实选择,一个很好的例子就是上传或下载大型文件。即使用户退出应用程序,上传和下载也可能会继续,并且您当然不想阻止用户在执行这些任务时使用应用程序。

作业调度程序

实际上,您必须使用JobInfo.Builder创建一个服务并创建一个作业,该作业指定了何时运行服务的条件。

RxJava语言

通过使用可观察序列来组合异步和基于事件的程序的库。

花冠(Kotlin)

它的主要要点是,它使异步代码看起来非常像同步代码

在这里、这里、这里和这里阅读更多信息。

这个问题有两种解决方案。

不要在主UI线程中使用网络调用。为此使用异步任务。在setContentView(R.layout.activity_main)之后,将以下代码写入MainActivity文件:如果(android.os.Build.VERSION.SDK_INT>9){StrictMode.ThreadPolicy policy=new StrictMode.SthreadPolicy.Builder().permitAll().build();StrictMode.setThreadPolicy(策略);}

以及下面的import语句到Java文件中。

import android.os.StrictMode;

使用以下代码执行繁重的任务。

// Your package here


import java.util.List;
import org.apache.http.NameValuePair;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.view.View.OnSystemUiVisibilityChangeListener;

public class AsyncRequest extends AsyncTask<String, Integer, String> {

    Context context;
    ProgressDialog pDialog;

    // Three Constructors
    public AsyncRequest(Activity a, String m, List<NameValuePair> p) {
        context = a;
        method = m;
        parameters = p;
    }

    public AsyncRequest(Activity a) {
        this.caller = (OnAsyncRequestComplete) a;
        context = a;
    }

    public String doInBackground(String... urls) {

        //Perform your task here
        return result;
    }

    public void onPreExecute() {
        pDialog = new ProgressDialog(context);
        pDialog.setMessage("Please wait..");
        pDialog.setCancelable(false);
        pDialog.show();
    }

    public void onProgressUpdate(Integer... progress) {
        // You can implement some progressBar and update it in this record.
        //   setProgressPercent(progress[0]);
    }

    public void onPostExecute(String response) {
        if (pDialog != null && pDialog.isShowing()) {
            pDialog.dismiss();
        }
        // Get the result here
    }

    protected void onCancelled(String response) {

        if (pDialog != null && pDialog.isShowing()) {
            pDialog.dismiss();
        }
    }
}

使用以下代码禁用严格模式:

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

不建议使用AsyncTask接口。

两种方法的完整代码