我在运行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 11中的Android AsyncTask API。

即使在主活动之外创建线程类,只要在main中调用它,也会得到相同的错误。调用必须在一个可运行的线程内,但如果您需要一些异步代码在后台执行或稍后在这里执行,您可以查看Kotlin和Java的一些替代方案:

*https://stackoverflow.com/questions/58767733/android-asynctask-api-deprecating-in-android-11-what-are-the-alternatives*

特别适合我的是mayank1513对上面链接中可运行线程的Java8实现的回答。代码如下:

new Thread(() -> {
        // do background stuff here
        runOnUiThread(()->{
            // OnPostExecute stuff here
        });
    }).start();

但是,您可以先在代码的某个部分定义线程,然后在其他地方启动它,如下所示:

线程定义

Thread thread = new Thread(() -> {
            // do background stuff here
            runOnUiThread(()->{
                // OnPostExecute stuff here
            });
        });

线程调用

thread.start();

我希望这可以让人省去看到不推荐的AsyncTask时的头疼。

其他回答

谷歌不推荐Android 11中的Android AsyncTask API。

即使在主活动之外创建线程类,只要在main中调用它,也会得到相同的错误。调用必须在一个可运行的线程内,但如果您需要一些异步代码在后台执行或稍后在这里执行,您可以查看Kotlin和Java的一些替代方案:

*https://stackoverflow.com/questions/58767733/android-asynctask-api-deprecating-in-android-11-what-are-the-alternatives*

特别适合我的是mayank1513对上面链接中可运行线程的Java8实现的回答。代码如下:

new Thread(() -> {
        // do background stuff here
        runOnUiThread(()->{
            // OnPostExecute stuff here
        });
    }).start();

但是,您可以先在代码的某个部分定义线程,然后在其他地方启动它,如下所示:

线程定义

Thread thread = new Thread(() -> {
            // do background stuff here
            runOnUiThread(()->{
                // OnPostExecute stuff here
            });
        });

线程调用

thread.start();

我希望这可以让人省去看到不推荐的AsyncTask时的头疼。

主线程是UI线程,您不能在主线程中执行可能会阻止用户交互的操作。您可以通过两种方式解决此问题:

强制在主线程中执行任务,如下所示

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);

有关更多信息,请查看:无痛线程

这些答案需要更新,以使用更现代的方式连接到Internet上的服务器,并处理一般的异步任务。

例如,您可以在GoogleDriveAPI示例中找到使用Tasks的示例。在这种情况下也应使用相同的方法。我将使用OP的原始代码来演示这种方法。

首先,您需要定义一个非主线程执行器,并且只需要执行一次:

private val mExecutor: Executor = Executors.newSingleThreadExecutor()

然后在该执行器中处理逻辑,该执行器将在主线程之外运行

Tasks.call (mExecutor, Callable<String> {

        val url = URL(urlToRssFeed)
        val factory = SAXParserFactory.newInstance()
        val parser = factory.newSAXParser()
        val xmlreader = parser.getXMLReader()
        val theRSSHandler = RssHandler()
        xmlreader.setContentHandler(theRSSHandler)
        val is = InputSource(url.openStream())
        xmlreader.parse(is)
        theRSSHandler.getFeed()

        // Complete processing and return a String or other object.
        // E.g., you could return Boolean indicating a success or failure.
        return@Callable someResult
}).continueWith{
    // it.result here is what your asynchronous task has returned
    processResult(it.result)
}

continueWith子句将在异步任务完成后执行,您将有权访问任务通过其.result返回的值。

不允许在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权限。它会像一个魅力一样发挥作用。:)

Executors.newFixedThreadPool(3).execute(() -> {
      //DO Task;        
 });