服务占用太多内存
我有一个服务,可以从 URL 中提取 html 代码,将其转换为仅文本(使用 Jsoup),然后检查字符串上的某些内容,如果某些条件成立,它会启动通知并将某些内容写入文件。 据我所知,这种服务不会占用太多内存,而在 Watchdog 中,它大约需要 65 MB,这太多了。它比任何其他进程都需要更多的时间(甚至比 tw 启动器和 Android 系统还要多)。 我想让你告诉我我做错了什么。
这是我的服务类:
public class NotifyService extends Service
{
private int number=0;
private Timer timer=new Timer();
private long INTERVAL=1*1000*60*60;//1 hour
public static String Oldhtml;
public static String Newhtml;
public static String currHtml;
// hooks main activity here
/*
* not using ipc...but if we use in future
*/
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate()
{
super.onCreate();
_startService();
Log.w("myApp", "START");
}
@Override
public void onDestroy()
{
super.onDestroy();
_shutdownService();
Log.w("myApp", "STOPPED");
}
/*
* starting the service
*/
private void _startService()
{
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
try {
doServiceWork();
} catch (ClientProtocolException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(INTERVAL);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},0,INTERVAL);
;
}
/*
* start the processing, the actual work, getting config params, get data from network etc
*/
private void doServiceWork() throws ClientProtocolException, IOException
{
String FILENAME="blichData";
String info=null;
String classLetter = null,classNum1=null;
int classNum = 0;
try{
FileInputStream fis=openFileInput(FILENAME);
byte[] dataArray = new byte[fis.available()];
while(fis.read(dataArray)!=-1)
{
info = new String(dataArray);
}
classLetter = info.substring(0, info.lastIndexOf(" "));
classNum1 =info.substring(info.lastIndexOf(" ")+1);
classNum=Integer.parseInt(classNum1);
fis.close();
}catch (Exception e){
}
if (classLetter!=null && classNum1!=null) {
Oldhtml=readHTMLfromFile();
if (GetHTML.isHavingChanges(classLetter,classNum))
{
myNotify();
writeHTMLtoFile(currHtml);
/*
try {
String data= "false";
FileOutputStream fos = openFileOutput("blichService", Context.MODE_PRIVATE);
fos = openFileOutput("blichService",Context.MODE_PRIVATE);
fos.write(data.getBytes());
fos.close();
}
catch (Exception e) {}
*/
}
}
;
}
/*
* shutting down the service
*/
private void _shutdownService()
{
if (timer != null) timer.cancel();
Log.i(getClass().getSimpleName(), "Timer stopped...");
}
public void writeHTMLtoFile(String html) {
try {
String FILENAME = "blichNotifyData";
String data= html;
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos = openFileOutput(FILENAME,Context.MODE_PRIVATE);
fos.write(data.getBytes());
fos.close();
}
catch (Exception e){}
}
public String readHTMLfromFile() {
String FILENAME = "blichNotifyData";
String info="";
try{
FileInputStream fis=openFileInput(FILENAME);
if (fis.available()>0)
{
byte[] dataArray = new byte[fis.available()];
while(fis.read(dataArray)!=-1)
{
info = new String(dataArray);
}
fis.close();
}
else {
Oldhtml="null";
}
}
catch (Exception e) {}
return info;
}
public void myNotify()
{
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent= new Intent (this,SchoolBlichActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);
String body = " בליך";
String title = "ישנם שינויים חדשים!";
Notification n =new Notification(R.drawable.table, body, System.currentTimeMillis());
n.flags |=Notification.FLAG_AUTO_CANCEL;
n.setLatestEventInfo(getApplicationContext(), title, body, pi);
n.defaults = Notification.DEFAULT_ALL;
number++;
n.number=number;
nm.notify(0,n);
}
}
如果需要,HTML 提取类:
public class GetHTML {
public static boolean isHavingChanges(String classLetter,int classNum) throws ClientProtocolException, IOException {
int classLetterCode = 0;
int timeTableCode=1;
if (classLetter.equals("ט"))
classLetterCode=0;
else if (classLetter.equals("י"))
classLetterCode=1;
else if (classLetter.equals("יא"))
classLetterCode=2;
else if (classLetter.equals("יב"))
classLetterCode=3;
switch(classLetterCode)
{
case 0:
if (classNum>=1 && classNum<=7)
timeTableCode=1;
else if (classNum>7 && classNum<=14)
timeTableCode=2;
break;
case 1:
if (classNum>=1 && classNum<=7)
timeTableCode=3;
else if (classNum>7 && classNum<=14)
timeTableCode=4;
break;
case 2:
if (classNum>=1 && classNum<=7)
timeTableCode=5;
else if (classNum>7 && classNum<=14)
timeTableCode=6;
break;
case 3:
if (classNum>=1 && classNum<=7)
timeTableCode=7;
else if (classNum>7 && classNum<=14)
timeTableCode=8;
break;
}
String url = "http://blich.iscool.co.il/DesktopModules/IS.TimeTable/MainScreen.aspx?pid=17&mid=6264&page="+timeTableCode+"&msgof=0&static=1";
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);
String html = "";
InputStream in = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder str = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null)
{
str.append(line);
}
in.close();
html = str.toString();
html = Jsoup.parse(html).text();
if (NotifyService.Oldhtml.equalsIgnoreCase(html)) {
return false;
}
if (timeTableCode%2!=0){
for (int i=0;i<8;i++) {
if (!html.contains(i+" "+i)) {
NotifyService.currHtml=html;
return true;
}
}
}
if (timeTableCode%2==0) {
for (int i=8;i<15;i++) {
if (!html.contains(i+" "+i)) {
NotifyService.currHtml=html;
return true;
}
}
}
return false;
}
}
忽略外语。 xD 我只是想了解我做错了什么? 谢谢
I have a service that extracting html code from an URL, converting it to text only (with Jsoup) and then checks something on the string, and if some conditions are true it launches a notification and writes something to a file.
As far as I know, this kind of service shouldn't take much memory, and in Watchdog, it takes ~65 MB, and it is way too much. It takes more than any other process (even more than tw launcher and Android System).
I would like you to tell me what have I done wrong.
Heres my service class:
public class NotifyService extends Service
{
private int number=0;
private Timer timer=new Timer();
private long INTERVAL=1*1000*60*60;//1 hour
public static String Oldhtml;
public static String Newhtml;
public static String currHtml;
// hooks main activity here
/*
* not using ipc...but if we use in future
*/
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate()
{
super.onCreate();
_startService();
Log.w("myApp", "START");
}
@Override
public void onDestroy()
{
super.onDestroy();
_shutdownService();
Log.w("myApp", "STOPPED");
}
/*
* starting the service
*/
private void _startService()
{
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
try {
doServiceWork();
} catch (ClientProtocolException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(INTERVAL);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},0,INTERVAL);
;
}
/*
* start the processing, the actual work, getting config params, get data from network etc
*/
private void doServiceWork() throws ClientProtocolException, IOException
{
String FILENAME="blichData";
String info=null;
String classLetter = null,classNum1=null;
int classNum = 0;
try{
FileInputStream fis=openFileInput(FILENAME);
byte[] dataArray = new byte[fis.available()];
while(fis.read(dataArray)!=-1)
{
info = new String(dataArray);
}
classLetter = info.substring(0, info.lastIndexOf(" "));
classNum1 =info.substring(info.lastIndexOf(" ")+1);
classNum=Integer.parseInt(classNum1);
fis.close();
}catch (Exception e){
}
if (classLetter!=null && classNum1!=null) {
Oldhtml=readHTMLfromFile();
if (GetHTML.isHavingChanges(classLetter,classNum))
{
myNotify();
writeHTMLtoFile(currHtml);
/*
try {
String data= "false";
FileOutputStream fos = openFileOutput("blichService", Context.MODE_PRIVATE);
fos = openFileOutput("blichService",Context.MODE_PRIVATE);
fos.write(data.getBytes());
fos.close();
}
catch (Exception e) {}
*/
}
}
;
}
/*
* shutting down the service
*/
private void _shutdownService()
{
if (timer != null) timer.cancel();
Log.i(getClass().getSimpleName(), "Timer stopped...");
}
public void writeHTMLtoFile(String html) {
try {
String FILENAME = "blichNotifyData";
String data= html;
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos = openFileOutput(FILENAME,Context.MODE_PRIVATE);
fos.write(data.getBytes());
fos.close();
}
catch (Exception e){}
}
public String readHTMLfromFile() {
String FILENAME = "blichNotifyData";
String info="";
try{
FileInputStream fis=openFileInput(FILENAME);
if (fis.available()>0)
{
byte[] dataArray = new byte[fis.available()];
while(fis.read(dataArray)!=-1)
{
info = new String(dataArray);
}
fis.close();
}
else {
Oldhtml="null";
}
}
catch (Exception e) {}
return info;
}
public void myNotify()
{
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent= new Intent (this,SchoolBlichActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);
String body = " בליך";
String title = "ישנם שינויים חדשים!";
Notification n =new Notification(R.drawable.table, body, System.currentTimeMillis());
n.flags |=Notification.FLAG_AUTO_CANCEL;
n.setLatestEventInfo(getApplicationContext(), title, body, pi);
n.defaults = Notification.DEFAULT_ALL;
number++;
n.number=number;
nm.notify(0,n);
}
}
And if it is needed, the HTML extracting class:
public class GetHTML {
public static boolean isHavingChanges(String classLetter,int classNum) throws ClientProtocolException, IOException {
int classLetterCode = 0;
int timeTableCode=1;
if (classLetter.equals("ט"))
classLetterCode=0;
else if (classLetter.equals("י"))
classLetterCode=1;
else if (classLetter.equals("יא"))
classLetterCode=2;
else if (classLetter.equals("יב"))
classLetterCode=3;
switch(classLetterCode)
{
case 0:
if (classNum>=1 && classNum<=7)
timeTableCode=1;
else if (classNum>7 && classNum<=14)
timeTableCode=2;
break;
case 1:
if (classNum>=1 && classNum<=7)
timeTableCode=3;
else if (classNum>7 && classNum<=14)
timeTableCode=4;
break;
case 2:
if (classNum>=1 && classNum<=7)
timeTableCode=5;
else if (classNum>7 && classNum<=14)
timeTableCode=6;
break;
case 3:
if (classNum>=1 && classNum<=7)
timeTableCode=7;
else if (classNum>7 && classNum<=14)
timeTableCode=8;
break;
}
String url = "http://blich.iscool.co.il/DesktopModules/IS.TimeTable/MainScreen.aspx?pid=17&mid=6264&page="+timeTableCode+"&msgof=0&static=1";
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);
String html = "";
InputStream in = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder str = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null)
{
str.append(line);
}
in.close();
html = str.toString();
html = Jsoup.parse(html).text();
if (NotifyService.Oldhtml.equalsIgnoreCase(html)) {
return false;
}
if (timeTableCode%2!=0){
for (int i=0;i<8;i++) {
if (!html.contains(i+" "+i)) {
NotifyService.currHtml=html;
return true;
}
}
}
if (timeTableCode%2==0) {
for (int i=8;i<15;i++) {
if (!html.contains(i+" "+i)) {
NotifyService.currHtml=html;
return true;
}
}
}
return false;
}
}
Ignore the foreign language. xD
I just want to understand what have I done wrong?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
虽然我无法直接判断代码的哪一部分有问题,但您可以尝试使用 Eclipse MAT 通过 DDMS 获取的堆转储来分析内存使用情况。您需要使用
hprofconv
工具将 Android 堆转储转换为 MAT 可以理解的格式。要获取 HPROF 堆转储,请打开 Dalvik 调试监视器 (DDMS),将其连接到您的模拟器,选择应用程序的进程,然后单击“转储 HPROF 文件”图标。
While I cannot tell out-of-the-box what portion of your code is problematic, you may try to analyze the memory usage through a heap dump taken with DDMS using Eclipse MAT. You will need to use the
hprofconv
tool to convert your Android heap dump into a format that MAT understands.To get the HPROF Heap Dump, open the Dalvik Debug Monitor (DDMS), connect it you your emulator, select the process of your application and hit the "Dump HPROF file" icon.