Android 服务冻结用户界面
我有一个从传感器数据计算步数的服务。这是一项持续运行的服务。我的服务正在运行,也正在执行所需的任务,但我的主要问题是它冻结了我的UI。如何更新UI而不冻结它 这是我的服务课: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
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线程上分派消息