java - 如何解决我的后台服务中的 "doing too much work on its main thread service"错误?

标签 java android multithreading service

我为我的应用程序创建了一个后台服务,但它显示错误“在其主线程服务上做了太多工作”。而且它使应用程序滞后到无法使用的程度。那么,我的代码有什么问题呢?

public class TestService extends Service {

    boolean serviceRun = true;
    SharedPreferences prefs;
    Editor editor;
    int serverId;
    int gameId;
    JSONObject jsonObj;
    NotificationManager m_notificationManager;
    int NOTIFICATION_ID = 0;

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

    public class MyBinder extends Binder {
        public TestService getService() {
            return TestService.this;
        }
    }

    private ServiceConnection m_serviceConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            Service m_service = ((TestService.MyBinder) service).getService();
        }

        public void onServiceDisconnected(ComponentName className) {
            Service m_service = null;
        }
    };

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        prefs = getSharedPreferences(Constants.PREFS_NAME, Context.MODE_PRIVATE);
        editor = prefs.edit();
        serverId = prefs.getInt(Constants.PREF_SERVER_ID, 0);

        Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();

        final Handler handler = new Handler() {

            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (isNetworkConnected()) {
                    for (int i = 0; i < prefs.getInt(Constants.PREF_FRIEND_COUNT, 0); i++) {
                        if (prefs.getBoolean(Constants.PREF_FRIEND_NOTIFICATION + i, true)) {

                            try {
                                jsonObj = new GetGames().execute(
                                        "apiurl.blabla").get();
                                gameId = jsonObj.getJSONArray(Constants.JSON_GAMES).getJSONObject(0)
                                        .getInt(Constants.JSON_GAME_ID);

                                if (gameId == prefs.getInt(Constants.PREF_LAST_GAME_ID + i, 0)) {

                                } else {

                                    if (!prefs.getBoolean(Constants.PREF_FRIEND_FIRST_TIME + i, false)) {

                                        addNotification(
                                                "Notification", i);
                                        NOTIFICATION_ID++;
                                    } else {
                                        editor.putBoolean(Constants.PREF_FRIEND_FIRST_TIME + i, false);
                                    }

                                    editor.putInt(Constants.PREF_LAST_GAME_ID + i, gameId);
                                    editor.commit();

                                }

                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            } catch (ExecutionException e) {
                                e.printStackTrace();
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }

                    }
                } else {

                }
            }

        };

        new Thread(new Runnable() {
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(Constants.SERVICE_LOOP_INTERVAL * 1000);
                        handler.sendEmptyMessage(0);

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }

            }
        }).start();

        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        Toast.makeText(this, "Service Stopped", Toast.LENGTH_SHORT).show();
        Intent intent = new Intent(this, TestService.class);
        bindService(intent, m_serviceConnection, BIND_AUTO_CREATE);
        super.onDestroy();
    }

    private boolean isNetworkConnected() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        return (cm.getActiveNetworkInfo() != null);
    }

    private void addNotification(String s, int i) {
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_launcher)
                .setContentTitle("Lol Stalker")
                .setContentText(
                        "Notification text");

        Intent resultIntent = new Intent(this, FriendProfileActivity.class);
        resultIntent.putExtra(Constants.FRIEND_NUMBER, i);
        try {
            resultIntent.putExtra(Constants.JSON, new startFriends().execute(prefs.getInt(Constants.PREF_FRIEND_ID + i, 0))
                    .get());
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // Because clicking the notification opens a new ("special") activity,
        // there's
        // no need to create an artificial back stack.
        PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        mBuilder.setContentIntent(resultPendingIntent);
        // Sets an ID for the notification
        int mNotificationId = 001;
        // Gets an instance of the NotificationManager service
        NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        // Builds the notification and issues it.
        mNotifyMgr.notify(mNotificationId, mBuilder.build());

    }

    private class startFriends extends AsyncTask<Integer, Integer, String> {

        @Override
        protected String doInBackground(Integer... params) {
            HttpClient client = new DefaultHttpClient();
            String geturl = "apiurl.com";
            HttpGet get = new HttpGet(geturl);
            HttpResponse responseGet = null;
            String response = null;
            try {
                responseGet = client.execute(get);
                HttpEntity resEntityGet = responseGet.getEntity();
                response = EntityUtils.toString(resEntityGet);
            } catch (Exception e) {
                e.printStackTrace();
            }

            return response;
        }
    }
}

所以基本上,我想要创建的是创建一个始终在设备后台运行的后台服务,在执行时重新启动。该服务执行一个异步任务,如果有网络连接,则每隔 X 秒进行一次 http 调用,并在满足条件时显示通知。然而,它滞后太多,导致应用程序无法使用。如何解决这个问题?

最佳答案

您正在异步任务的execute() 上调用.get()。因此它不再是异步的。删除 .get() 并将以下代码行放在异步任务的 onPostExecute 中。

为什么使用处理程序作为中间任务和额外的异步任务,您可以在线程中完成所有操作?

关于java - 如何解决我的后台服务中的 "doing too much work on its main thread service"错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24692902/

相关文章:

java - 将 C 中的 crc8 函数转换为 Java

Java:检查oracle字段类型NUMBER(6,4)的值是否等于0

android - 有什么方法可以告诉 Android 操作系统不要为 "Internet"使用连接的 Wi-Fi 网络?

java - Activity 销毁或重启期间的后台工作

java - response.sendRedirect() 未正确重定向

java - 在 Java 中扩展双引号内的变量

android - 地理空间栅栏关系 w.r.t 个人设备?

java - 如何触发 intent 以启动 flv 或 swf 到 Flash Player 10.1?

c# - C# 中的 lock 关键字

python - 如何使用线程来创建多个独立的可重用对象实例?