【问题标题】:How to use AsyncTask in Services in Android?如何在 Android 的服务中使用 AsyncTask?
【发布时间】:2013-09-20 09:36:00
【问题描述】:

我试图在下面运行它给出异常的代码:

 java.lang.RuntimeException: Unable to start service com.example.testfeeds.UpdateWidgetService@410a33c8 with Intent {  cmp=com.example.testfeeds/.UpdateWidgetService (has extras) }: android.os.NetworkOnMainThreadException

据我了解,新版本的 Android 不允许在主线程中进行网络操作。人们建议我使用异步任务 但我不知道如何使用它。有人可以在下面的代码中告诉我吗?

提前致谢

public class WidgetService extends Service {
/*
 * So pretty simple just defining the Adapter of the listview
 * here Adapter is ListProvider
 * */

/*@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
    int appWidgetId = intent.getIntExtra(
            AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID);

    return (new ListProvider(this.getApplicationContext(), intent));
}*/

public static int numberOfItems=0;
  //numberOfItems=0;
    private static  String LOG = "testwidgets";
    ArrayList<String> feedsPubDate;
      @SuppressWarnings("deprecation")
    @Override
      public void onStart(Intent intent, int startId) {
        Log.i(LOG, "Called");
        // Create some random data
        feedsPubDate=new ArrayList<String>(); 
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this .getApplicationContext());
        int[] allWidgetIds = intent
            .getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
        ComponentName thisWidget = new ComponentName(getApplicationContext(), WidgetProvider.class);
        int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget);
        Log.w(LOG, "From Intent" + String.valueOf(allWidgetIds.length));
        Log.w(LOG, "Direct" + String.valueOf(allWidgetIds2.length));
        for (int widgetId : allWidgetIds) {
          // Create some random data
/////////////////////////////////////////////////////////////////////////// 

              RemoteViews remoteViews = new RemoteViews(this.getApplicationContext().getPackageName(),
              R.layout.widget_layout);
          Log.d("numberOfItems intially", String.valueOf(numberOfItems));
              try {
                numberOfItems=doTestFeed();
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
          // Set the text
          remoteViews.setTextColor(R.id.empty_view,Color.WHITE);
          remoteViews.setTextViewText(R.id.empty_view,"  "+ String.valueOf(numberOfItems));
          Log.w(LOG, String.valueOf(numberOfItems));
////////////////////////////////////////////////////////////////////////////

          // Register an onClickListener
          Intent clickIntent = new Intent(this.getApplicationContext(),
              WidgetProvider.class);
          clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
          clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,
              allWidgetIds);
          PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, clickIntent,
              PendingIntent.FLAG_UPDATE_CURRENT);
          remoteViews.setOnClickPendingIntent(R.id.empty_view, pendingIntent);
          appWidgetManager.updateAppWidget(widgetId, remoteViews);
        }
        stopSelf();
        super.onStart(intent, startId);

      }



    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }


    int doTestFeed() throws MalformedURLException, ParseException
    {  
        Log.d("msg"," in do test feed");
        InputStream is = null;
        int x = 0;
        URL myURL = new URL("http://yunn.yu.edu.jo/index.php?option=com_content&view=category&id=55&layout=blog&Itemid=104&format=feed&type=rss");
        try {
            URLConnection conn = myURL.openConnection();
             is = conn.getInputStream();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        XmlPullParserFactory pullParserFactory;
        try {
            pullParserFactory = XmlPullParserFactory.newInstance();
            XmlPullParser parser = pullParserFactory.newPullParser();
                parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
                parser.setInput(is, null);
                Log.d("msg","before making parsing");
                x=parseXML(parser);
                Log.d("msg","after making parsing");
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.d("msg"," done testing");
        return x;
    }
//////////////////////////////////////////////////////////////////////////////////
    @SuppressLint("SimpleDateFormat")
    private int parseXML(XmlPullParser parser) throws XmlPullParserException,IOException, ParseException
    {
        Log.d("msg"," in parser");
        int eventType = parser.getEventType();
        int getElement=0;
        String pubDate=null;
        while (eventType != XmlPullParser.END_DOCUMENT){
            String tagName = null;
            switch (eventType){
            //----------------------------------//
            case XmlPullParser.START_DOCUMENT: 
                {
                    // do nothing
                }
                break;
           //----------------------------------//
             case XmlPullParser.START_TAG:
             { tagName = parser.getName();
                 if ("item".equals(tagName)){
                      getElement=1;
                 } else if (getElement!=0){
                      if ("pubDate".equals(tagName)){
                         pubDate= parser.nextText();
                         feedsPubDate.add(pubDate);
                         Log.d("value",pubDate);
                     }
                 }
             }
                 break;                     
           //----------------------------------//
             case XmlPullParser.END_TAG:
             { tagName = parser.getName();
                 if (tagName.equalsIgnoreCase("item") && getElement != 0){
                 }
             }
                 break;
          //----------------------------------//
            }// end-switch.
            eventType= parser.next();
        }// end-while.
        int i=0;
        SharedPreferences sp = getSharedPreferences("tempData", 0);
        String dateStringA=sp.getString("recentPubDate", null);
        Log.d("oldest date",dateStringA);
        for(String s : feedsPubDate )
        {
        String dateStringB = feedsPubDate.get(i);
        SimpleDateFormat parserSDF = new SimpleDateFormat("EEE, DD MMM yyyy HH:mm:ss");
        Date dateA = null;
        try {
            dateA = parserSDF.parse(dateStringA);
        } catch (java.text.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Date dateB = null;
        try {
            dateB = parserSDF.parse(dateStringB);
        } catch (java.text.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if (dateA.compareTo(dateB) < 0) {
            Log.d("imp msg","one new item");
            numberOfItems++;
        }
        i++;
        }
        Log.d("update result", String.valueOf(numberOfItems));
      // Toast.makeText(GeneralNews.this,"The size of the list"+feedsTitles.size() , Toast.LENGTH_LONG).show();
   return numberOfItems;
    } //end xmlParser method.
//////////////////////////////////////////////////////////////////////////////////
 }

【问题讨论】:

  • 请删除不相关的代码以帮助我们解决您的问题。
  • 和你在活动中使用的一样!

标签: android asynchronous service android-asynctask


【解决方案1】:

我认为这个问题可能对你有帮助:How to use AsyncTask

您可以将 AsyncTask 设为 Service 的内部类,并在 AsyncTask 的 doInBackground() 方法中执行网络操作。从 doInBackground() 你可以返回任何类型的数据到 AsyncTask 的 onPostExecute() 方法,在那里你可以对接收到的数据做进一步的事情。

这里是一个 AsyncTask 示例:AsyncTask Android example

【讨论】:

  • 好的,所以我必须从 Service 类的 onStartCommand 方法调用 AsyncTask?
【解决方案2】:

它是关于 ui 线程的。我猜服务有一些关于 ui 线程的问题。 onPostExecutes 必须在 ui 线程上运行。所以,由于Services没有ui线程,在非ui线程上执行onPostExecute时中断。

我建议

new Thread(){
        public void run() {
            Object result=null;


            Looper l = Looper.getMainLooper();
            Handler h = new Handler(l);
            h.post(new Runnable() {
                @Override
                public void run() {
                    if (result != null){
                        response.OnResponse(true, "", result);
                    } else {
                        response.OnResponse(false, errMessage, null);
                    }
                }
            });
        };
    }.start();

当然,这在 AsyncTask 中没有线程池,但是你可以将这段代码转换为使用线程池。

【讨论】:

  • 老实说,我不会推荐线程池,它的结果非常不可预测。
【解决方案3】:

一个简单的例子:

public class YourAsyncTask extends AsyncTask<String, Void, String>{

    @Override
    protected String doInBackground(String... params) {
        // your load work
        return myString;
    }

    @Override
    protected void onPostExecute(String result) {

    }

}

使用新的YourAsyncTask ().execute() 调用它。

【讨论】:

    【解决方案4】:

    例如:

    您已登录 Activity,当您按下“登录”时,应用程序需要验证 Service 并切换到主 Activity:

    private class HeavyTask extends AsyncTask<String, Void, Void> {
    
    
        protected Void doInBackground(String... args) {
    
            //do something here
            // like tell to Service to do some async task
    
            return null;
        }
    
        protected void onPostExecute(Void results) {
    
           // here actually we wait any event from Service about task done
    
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {                         
                            startActivity(new Intent().setClass(FirstLoginActivity.this, MainActivity.class).setData(getIntent().getData()));
    
                            finish();
                        }
                    }, 1000);
                }
            }, 500);            
        }       
    }
    

    这就是我所说的:

    HeavyTask task = new HeavyTask();
    task.execute(user, passwordText, login_outbound_proxy); // as example
    

    非常简单的例子,除了理论之外还可以帮助您解决问题

    【讨论】:

    • 谢谢Maxim,它适用于我们在活动中做的服务吗?
    • AsyncTask 是一种简短的服务方式。您可以决定 Service 或 AsyncTask。进入服务,您可以使用单个线程,但如果您从服务更新 GUI,请通过 Handler 使用它
    【解决方案5】:

    如果 API 版本是 11 或更高版本 android:targetSDk 不允许在主线程上运行 netwrok 但它在 HoneyComb.n 中可以正常工作

    尝试从清单中删除 android:targetSdkVersion 行。 我在 3rd 方代码中执行此操作,并且大部分时间都在为我工作。

    它对我有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-22
      • 1970-01-01
      • 2017-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多