Android 服务冻结用户界面

Android 服务冻结用户界面,android,service,Android,Service,我有一个从传感器数据计算步数的服务。这是一项持续运行的服务。我的服务正在运行,也正在执行所需的任务,但我的主要问题是它冻结了我的UI。如何更新UI而不冻结它 这是我的服务课: public class StepCounterService extends Service { private static final String LOG_TAG = "ForegroundService"; public static Boolean FLAG = false; pri

我有一个从传感器数据计算步数的服务。这是一项持续运行的服务。我的服务正在运行,也正在执行所需的任务,但我的主要问题是它冻结了我的UI。如何更新UI而不冻结它

这是我的服务课:

public class StepCounterService extends Service {
    private static final String LOG_TAG = "ForegroundService";

    public static Boolean FLAG = false;

    private SensorManager mSensorManager;
    private StepDetector detector;

    private PowerManager mPowerManager;
    private WakeLock mWakeLock;


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

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

        startServiceForeground(intent, flags, startId);


        return START_STICKY;
    }

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


        FLAG = true;

        Log.e("Service_Started", "");
        detector = new StepDetector(this);


        mSensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);

        mSensorManager.registerListener(detector,
                mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                SensorManager.SENSOR_DELAY_NORMAL);


        mPowerManager = (PowerManager) this
                .getSystemService(Context.POWER_SERVICE);
        mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK
                | PowerManager.ACQUIRE_CAUSES_WAKEUP, "S");
        mWakeLock.acquire();
        reloadSettings();
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        FLAG = false;
        if (detector != null) {
            mSensorManager.unregisterListener(detector);
        }

        if (mWakeLock != null) {
            mWakeLock.release();
        }

        Log.e("Service_destroyed", "");
    }

    public void reloadSettings() {

        if (detector != null) {
            detector.setSensitivity(
                    Float.valueOf("10")
            );
        }


    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        Intent restartService = new Intent(getApplicationContext(),
                this.getClass());
        restartService.setPackage(getPackageName());
        PendingIntent restartServicePI = PendingIntent.getService(
                getApplicationContext(), 1, restartService,
                PendingIntent.FLAG_ONE_SHOT);

        //Restart the service once it has been killed android

        ((AlarmManager) getSystemService(Context.ALARM_SERVICE))
                .set(AlarmManager.RTC, System.currentTimeMillis() + 1000, PendingIntent
                        .getService(this, 3, new Intent(this, StepCounterService.class), 0));

    }

    public int startServiceForeground(Intent intent, int flags, int startId) {
        Intent notificationIntent = new Intent(this, HomeActivity.class);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        Notification notification = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Mobiefit Walk")
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .build();
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(300, notification);
        Notification n;

        startForeground(300, notification);

        return START_STICKY;
    }


}
这是我的UpdatesTecount方法,它在接口类中声明,我在单独的类中实现它:

public void UpdateStepCount(final int steps) {
        if (Target_Goal == 0) {
            Target_Goal = 10000;
        }
        resetData(steps);

        Log.i("Narendra", "Total Steps:::" + String.valueOf(total_steps) + "::Steps::" + steps + "::getlast count:" + MobieFitWalkApp.getInstance().getLastStepCount());
        total_steps = steps - MobieFitWalkApp.getInstance().getLastStepCount();
        Log.i("getDistance",String.valueOf(Utilities.convertKilometersToMeters(getDistance(total_steps))));
        Log.i("CountCalories",String.valueOf(countCalories(total_steps)));
       // sessionDetails = SummaryManager.singleton().getLastFreeWalkData((Activity) mContext);

       // getFreeWalkData(total_steps);

        updateNotification(total_steps);
        if (needToStore) {

            if (dbController != null) {
                if (dbController.isTodayDataPresent(getCurrentDate())) {
                    //we need to get data from db
                    //calibrate previous and current data
                    //we need to write code for update data in db

                    dbController.updateSteps(String.valueOf(getDistance(total_steps)), String.valueOf(""), String.valueOf(total_steps), String.valueOf((Utilities.round(countCalories(total_steps), 2))));
                    needToStore = false;
                } else {
                    //insert new row
                    storeStepsDataInDb(total_steps);
                    needToStore = false;

                }
            }
            //call back will take total_steps,kcal,distance
            if (updateUI != null) {
                updateUI.UpdateBackgroundStepsUI(total_steps, getDistance(total_steps), countCalories(total_steps));
            }


            new Handler().postDelayed(new Runnable() {
                public void run() {
                    // Log.i("xxx", "Sensor changed");
                    needToStore = true;

                }
            }, 1000);
        }

    }

有人能告诉我如何阻止我的UI冻结吗?< /P> < P>如果在UI线程中执行长操作,那么在后台线程(异步任务)

中,必须考虑<代码>服务< /代码>在<代码>主线程< /代码>上工作。您可以选择在另一个线程上运行的
IntentService
,而不是使用
Service


冻结UI的可能情况是您的<代码>服务>代码>可能执行长时间运行的操作。

< P>如果您正在执行长时间的服务操作,请考虑使用HANDLRY线程、异步任务或IntService,或线程来执行长时间运行的任务。

服务总是在主线程中运行,您可以将其称为ui线程,因此,当您在服务内部执行长时间运行的任务时,它将阻止ui线程,因为它在主线程上运行,并且您正在同一线程上尝试长时间运行操作,因此如果您真的想使用具有长时间运行任务的服务,您可以选择在服务中创建asynTask或线程,并在asyncTask或线程中执行所有此类操作

第二种解决方案,您可以使用IntentService。IntentService在工作线程(也称为后台线程)中运行,因此您无需费心维护asynctask等,它保证您的ui永远不会阻塞。

警告:服务在其托管进程的主线程中运行;除非您另行指定,否则服务不会创建自己的线程,也不会在单独的进程中运行。如果您的服务要执行任何CPU密集型工作或阻塞操作,如MP3播放或联网,您应该在服务中创建一个新线程来完成该工作。通过使用单独的线程,您可以降低应用程序不响应(ANR)错误的风险,并且应用程序的主线程可以保持专用于用户与活动的交互


在IntentServiceIntentService中使用AsyncTask是按需处理异步请求(表示为Intent)的服务的基类。客户端通过startService(Intent)调用发送请求;该服务根据需要启动,使用工作线程依次处理每个意图,并在工作结束时自行停止。因此IntentService生成一个工作线程。您可以只使用处理程序mHandler=new处理程序(Looper.getMainLooper());在UI线程上分派消息