我在运行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

如何解决此问题?


当前回答

不使用strictMode(仅在调试模式下)不更改SDK版本不要使用单独的线程

使用服务或异步任务

另请参阅堆栈溢出问题:

android.os.NetworkOnMainThreadException从android发送电子邮件

其他回答

Kotlin版本

internal class RetrieveFeedTask : AsyncTask<String, Void, RSSFeed>() {

    override fun doInBackground(vararg urls: String): RSSFeed? {

        try {
             // download
             // prepare RSSFeeds
             return RSSFeeds

         } catch (e: Exception) {

            //handle exception
            return null
        }
    }

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

调用示例,

RetrieveFeedTask().execute(url)

您可以将代码的一部分移动到另一个线程中以卸载主线程,并避免获得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)

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

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

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

但如果您愿意接受后果,则可以取消此限制,并覆盖默认行为。

Add:

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

StrictMode.setThreadPolicy(policy);

在你的课堂上,

and

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

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

后果:

你的应用程序(在互联网连接不稳定的地区)将变得无响应并被锁定,用户感觉到速度缓慢,必须进行强制关闭,你冒着活动管理器关闭你的应用并告诉用户应用程序已停止的风险。

Android提供了一些关于良好编程实践的好建议,以设计响应能力:NetworkOnMainThreadException | Android开发人员

由于Android是在单个线程上工作的,因此您不应该在主线程上执行任何网络操作。有多种方法可以避免这种情况。

使用以下方法执行网络操作

Asysnctask:用于不需要太多时间的小型手术。意向服务:用于需要大量时间的网络操作。使用Volley和Modification等自定义库进行处理复杂网络操作

千万不要使用StrictMode.setThreadPolicy(策略),因为它会冻结您的UI,根本不是一个好主意。

在活动中使用此项

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