#android
#Android
Вопрос:
я работаю над приложениями для планировщика задач в качестве моего проекта в колледже, у меня есть сервис, который проверяет время истечения задачи. я внедрил обработчики для проверки времени истечения срока действия. Когда время истечения срока действия приложения совпадает с текущим временем, оно отправляет уведомление в строке состояния. На данный момент я приостанавливаю поток, используя метод Thread.sleep, на минуту, что приводит к зависанию моего приложения. В logcat это показывает интенсивное использование процессора приложениями.
я извлекаю данные из базы данных, но это работает нормально, когда Thread.sleep
не вызывается. Пожалуйста, помогите.
Вот код:
package com.apps.niit.taskm;
import java.util.ArrayList;
import java.util.Calendar;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class ExpireTimeService extends Service {
DataHelper dh;
ArrayList<String> tData=new ArrayList<String>();
String date;
Calendar c;
String str;
String str1;
String str2;
String str3;
String str4;
String str5;
int notificationID=1;
String [][] data;
NotificationManager notificationManager;
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate(){
super.onCreate();
dh = new DataHelper(this);
fetchData();
handler.removeCallbacks(updateTimeTask);
handler.postDelayed(updateTimeTask, 1000);
}
public void fetchData(){
String eDate = android.text.format.DateFormat.format("d/M/yyyy", new java.util.Date()).toString();
tData.addAll(this.dh.selectDate(eDate));
data =new String[tData.size()][4];
if(!tData.isEmpty()){
for(int i=0; i<tData.size();i ){
breakString(tData.get(i));
data[i][0]=str1;
data[i][1]=str2;
data[i][2]=str3;
data[i][3]=str4;
}
}
}
public void stopService(){
stopSelf();
}
private Runnable updateTimeTask = new Runnable() {
public void run(){
try {
String time = android.text.format.DateFormat.format("k:m", new java.util.Date()).toString();
for(int i=0; i<tData.size();i ){
if(data[i][3].equals(time)){
//send notification code goes here
String serName = Context.NOTIFICATION_SERVICE;
notificationManager = (NotificationManager)getSystemService(serName);
String ticker= data[i][0] " " data[i][1] " " data[i][2] " " data[i][3];
long when= System.currentTimeMillis();
int icon = R.drawable.icon;
Notification notification = new Notification(icon, ticker,when);
Intent intent = new Intent (getApplicationContext(), DisplayTask.class);
Bundle myBundle = new Bundle();
myBundle.putString("str1", data[i][0]);
myBundle.putString("str2", data[i][1]);Log.i("data1",data[i][1]);
myBundle.putString("str3", data[i][2]);Log.i("data1",data[i][2]);
myBundle.putString("str4", data[i][3]);Log.i("data1",data[i][3]);
intent.putExtras(myBundle);
PendingIntent launchIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
notification.setLatestEventInfo(getApplicationContext(), "", "", launchIntent);
notificationID=1;
notificationManager.notify(notificationID, notification);
Thread.sleep(10000);
}
}
handler.postDelayed(this, 1000);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.e("Error from service", e.toString());
}
}
};
private void breakString(String str) {
// TODO Auto-generated method stub
str1 = str.substring(0, str.indexOf(";"));
str = str.substring(str1.length() 1, str.length());
str2 = str.substring(0, str.indexOf(";"));
str = str.substring(str2.length() 1, str.length());
str3 = str.substring(0, str.indexOf(";"));
str4 = str.substring(str3.length() 1, str.length());
}
@Override
public void onDestroy() {
super.onDestroy();
if (handler != null)
handler.removeCallbacks(updateTimeTask);
handler = null;
}
private Handler handler = new Handler();
}
Ответ №1:
Когда вы используете Handler
postDelayed
функцию, вот что происходит:
- Обработчик помещает ваш
Runnable
в очередь циклирования текущего потока. - Когда придет время, ваш код
Runnable
будет запущен в потоке пользовательского интерфейса.
Обратите внимание, что это не то, что Handler
всегда помещает Runnable
в очередь потоков пользовательского интерфейса. Это помещает Runnable
в очередь текущего потока, а вашим текущим потоком был поток пользовательского интерфейса.
Итак, если вы добавите Thread.sleep
или что-нибудь еще, требующее много времени (например, сетевое взаимодействие), updateTimeTask
это приведет к зависанию всего потока пользовательского интерфейса.
В вашем случае вам следует использовать ScheduledExecutorService
, см. scheduleWithFixedDelay
функцию. Или, в качестве альтернативы, вы можете начать AsyncTask
со своей updateTimeTask
функции и выполнять всю тяжелую работу Thread.sleep
в doInBackgrund
функции.
Комментарии:
1. проблема решена с помощью другой альтернативы, использующей handler.postDelayed(<time>); notifyAll(); но возникла другая проблема — он будет отправлять только одно уведомление в минуту. например, в моем коде есть две задачи с одинаковым временем, тогда он будет показывать уведомление только за это время.
2. другим решением этой проблемы является время сопоставления в формате hh: mm: ss