我有一个简单的 Activity ,需要 Activity 10-15 分钟。该 Activity 使用 TelephonyManager 获取三个 LTE 参数:RSRP、RSRQ、PCI。它每秒收集一次这三个参数和一个时间戳,因此 UI 每秒更新一次。
用于获取 LTE 参数的方法在后台线程上运行。除了 UI 每秒更新之外,没有什么是计算密集型的。但是,如果我运行该 Activity 超过五分钟,则会收到可爱的 Android Monitor 消息:“I/Choreographer:跳过 91 帧!应用程序可能在其主线程上执行了太多工作。”
所以我一定做错了什么,因为我相信我正在后台线程上完成所有艰苦的工作。如果我运行该 Activity 10-15 分钟,它将跳过约 1,000 帧。然后,如果我浏览该应用程序并按下按钮运行另一个测试,它将开始跳过与前一个 15 分钟测试结束时一样多的帧,到第二个测试结束时,它可以跳过多达 2500 帧帧。然后,每次按下按钮开始下一个 Activity 所需的时间就会越来越长(即使是在实际上什么也没做的 Activity 中)。而且只有五项 Activity !
这是我需要主动收集数据 15 分钟的 Activity 的屏幕截图:
这是我名为 Third.java 的 Activity 的代码:
package com.parksjg.its.pscrindoortesttool;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.CellInfo;
import android.telephony.CellInfoLte;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import au.com.bytecode.opencsv.CSVWriter;
/**
* Created by josephparks on 1/27/16.
*/
public class Third extends Activity implements Runnable {
SignalStrengthListener signalStrengthListener;
TextView lteRsrp;
TextView lteRsrq;
TextView cellPciTextView, fileName;
ImageView img;
Button stopButton;
TelephonyManager tm;
List<CellInfo> cellInfoList;
String lte1, lte2;
int cellPci = 0;
ArrayList data;
CSVWriter writer;
String mydate;
String startDate;
boolean done = false;
@Override
public void run() {
// Moves the current Thread into the background
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
// This runs the code to grab the LTE parameters
startTele();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.third_activity);
// Sets up the TextViews and UI
setupUI();
// Runs telephony method on background thread
run();
// takes the collected data and adds it to the CSV format once per second
setupCSV();
// Sets up the stop button, writes data to CSV, and starts next activity
setupButton();
}
// This method is called by startTele() and is responsible for grabbing the LTE params
private class SignalStrengthListener extends PhoneStateListener {
@Override
public void onSignalStrengthsChanged(android.telephony.SignalStrength signalStrength) {
((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).listen(signalStrengthListener, SignalStrengthListener.LISTEN_SIGNAL_STRENGTHS);
tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String ltestr = signalStrength.toString();
String[] parts = ltestr.split(" ");
lte1 = parts[9];
lte2 = parts[10];
try {
cellInfoList = tm.getAllCellInfo();
for (CellInfo cellInfo : cellInfoList) {
if (cellInfo instanceof CellInfoLte) {
// cast to CellInfoLte and call all the CellInfoLte methods you need
// Gets the LTE PCI: (returns Physical Cell Id 0..503, Integer.MAX_VALUE if unknown)
cellPci = ((CellInfoLte) cellInfo).getCellIdentity().getPci();
}
}
} catch (Exception e) {
// Log.d("SignalStrength", "+++++++++++++++++++++++++++++++ null array spot 3: " + e);
}
// Gets the timestamp of when these LTE params where collected
mydate = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
// Updates the UI TextViews for RSRP, RSRQ, and PCI
lteRsrp.setText(String.valueOf(lte1));
lteRsrq.setText(String.valueOf(lte2));
cellPciTextView.setText(String.valueOf(cellPci));
super.onSignalStrengthsChanged(signalStrength);
}
}
// This takes the collected LTE data and timestamps and concatenates them into one object
// which is then easy to create a CSV file from
private void setupCSV() {
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
data.add(new String[]{mydate, lte1, lte2, String.valueOf(cellPci)});
}
}, 0, 1000);//put here time 1000 milliseconds=1 second
}
private void setupUI () {
data = new ArrayList();
// startDate is used to name the CSV file
startDate = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
lteRsrp = (TextView) findViewById(R.id.lteRsrp);
lteRsrq = (TextView) findViewById(R.id.lteRsrq);
cellPciTextView = (TextView) findViewById(R.id.cellPciTextView);
fileName = (TextView) findViewById(R.id.fileName);
fileName.setText(startDate);
stopButton = (Button) findViewById(R.id.stopButton);
img = (ImageView) findViewById(R.id.imageView);
img.setImageResource(R.drawable.recording);
// Log.d("Time and Date", "+++++++++++++ DATE : " + mydate);
}
private void startTele() {
// start the signal strength listener
signalStrengthListener = new SignalStrengthListener();
((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).listen(signalStrengthListener, SignalStrengthListener.LISTEN_SIGNAL_STRENGTHS);
tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
try {
cellInfoList = tm.getAllCellInfo();
} catch (Exception e) {
// Log.d("SignalStrength", "+++++++++++++++++++++++++++++++++++++++++ null array spot 1: " + e);
}
}
private void setupButton() {
stopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(Third.this, "Writing output to CSV!", Toast.LENGTH_LONG).show();
// Writes the data to a CSV file named by startDate
writeCSV();
try{
if(signalStrengthListener != null) {
tm.listen(signalStrengthListener, SignalStrengthListener.LISTEN_NONE);
// Log.d("TAG", "+++++++++++++++++++++++++++++++++++ Stop button Success!!!!!!");
}
}catch(Exception e){
e.printStackTrace();
// Log.d("TAG", "+++++++++++++++++++++++++++++++++++ Stop button Fail!!!!!! with error = " + e);
}
// Intent passes startDate and the boolean done to indicate when the CSV has been written
Intent intent = new Intent(getBaseContext(), Fourth.class);
intent.putExtra("START_DATE", startDate);
intent.putExtra("DONE", done);
startActivity(intent);
finish();
}
});
}
private void writeCSV() {
try {
File file = new File(getExternalFilesDir(null), startDate+".csv");
writer = new CSVWriter(new FileWriter(file, true), ',');
// Headers
String[] headers = "Time, RSRP, RSRQ, PCI".split(",");
writer.writeNext(headers);
writer.writeAll(data);
writer.flush();
writer.close();
Toast.makeText(Third.this, "CSV Successful!", Toast.LENGTH_SHORT).show();
done = true;
// Log.d("CSV Writer", "CSV Writer Successful!");
} catch (IOException e) {
// Log.d("CSV Writer", "Error writing CSV file : " + e);
Toast.makeText(Third.this, "Error writing CSV file", Toast.LENGTH_SHORT).show();
}
}
}
下面是名为third_activity.xml 的相应 XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffdc1d">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Recording"
android:textSize="26sp"
android:textColor="#000000"
android:id="@+id/lteRecording"
android:layout_alignParentTop="true"
android:textAlignment="center"
android:background="#f91616"
android:textStyle="bold"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:paddingTop="10dp"
android:paddingBottom="10dp" />
<TextView
android:layout_width="210dp"
android:layout_height="wrap_content"
android:text="0"
android:textSize="22sp"
android:textColor="#000000"
android:id="@+id/lteRsrp"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_marginStart="29dp"
android:layout_marginTop="120dp"
android:textAlignment="textEnd"
android:background="#ffdc1d"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="= LTE RSRP"
android:textSize="22sp"
android:textColor="#000000"
android:id="@+id/textView2"
android:background="#ffdc1d"
android:textStyle="bold"
android:layout_alignTop="@+id/lteRsrp"
android:layout_toEndOf="@+id/stopButton" />
<TextView
android:layout_width="210dp"
android:layout_height="wrap_content"
android:text="0"
android:textColor="#a71b1b"
android:textSize="22sp"
android:id="@+id/lteRsrq"
android:layout_below="@+id/lteRsrp"
android:layout_alignStart="@+id/lteRsrp"
android:textAlignment="textEnd"
android:textStyle="bold"
android:background="#ffdc1d"
android:layout_marginTop="20dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="= LTE RSRQ"
android:textSize="22sp"
android:textColor="#a71b1b"
android:id="@+id/textView3"
android:layout_below="@+id/textView2"
android:layout_alignStart="@+id/textView2"
android:textStyle="bold"
android:background="#ffdc1d"
android:layout_marginTop="20dp" />
<TextView
android:layout_width="210dp"
android:layout_height="wrap_content"
android:text="0"
android:textSize="22sp"
android:textColor="#075f09"
android:id="@+id/cellPciTextView"
android:layout_below="@+id/lteRsrq"
android:layout_alignStart="@+id/lteRsrq"
android:textAlignment="textEnd"
android:background="#ffdc1d"
android:textStyle="bold"
android:layout_marginTop="20dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="= LTE PCI"
android:textSize="22sp"
android:textColor="#075f09"
android:id="@+id/textView4"
android:layout_below="@+id/textView3"
android:layout_alignStart="@+id/textView3"
android:background="#ffdc1d"
android:textStyle="bold"
android:layout_marginTop="20dp" />
<Button
android:layout_width="120dp"
android:layout_height="wrap_content"
android:text="Stop"
android:textSize="22sp"
android:textColor="#ffdc1d"
android:id="@+id/stopButton"
android:background="#f91616"
android:textStyle="bold"
android:padding="4dp"
android:textAlignment="center"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="41dp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"
android:src="@drawable/recording"
android:layout_above="@+id/textView2"
android:layout_alignStart="@+id/lteRsrp"
android:layout_marginBottom="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Filename:"
android:textColor="#000000"
android:textSize="26sp"
android:id="@+id/textView6"
android:layout_marginTop="50dp"
android:layout_below="@+id/cellPciTextView"
android:layout_alignStart="@+id/cellPciTextView"
android:textStyle="bold|italic" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textColor="#000000"
android:textSize="26sp"
android:id="@+id/fileName"
android:layout_below="@+id/textView6"
android:layout_centerHorizontal="true"
android:textStyle="bold" />
</RelativeLayout>
这是 AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.parksjg.its.pscrindoortesttool" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity android:name=".First"
android:screenOrientation="portrait"
android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Second"
android:screenOrientation="portrait"
android:noHistory="true">
</activity>
<activity android:name=".Third"
android:screenOrientation="portrait"
android:noHistory="true">
</activity>
<activity android:name=".Fourth"
android:screenOrientation="portrait"
android:noHistory="true">
</activity>
<activity android:name=".Final"
android:screenOrientation="portrait"
android:noHistory="true">
</activity>
</application>
</manifest>
我是否在后台线程中执行了错误的代码?我怎样才能让这个运行更流畅、 react 更灵敏?同样,运行时间在 5 分钟以内时速度很快,但我们用它来测试研究室内 LTE 网络,我们的步行测试/驾驶测试需要 10-15 分钟,但当我按下停止按钮或新的测试按钮时,我需要它在一两秒内做出响应。有时,按下按钮后,操作需要 20-30 秒才能生效,特别是在连续测试后。
以下是应用程序的完整流程:
上一个 Activity 的按钮将重新启动第二个 Activity 。如果您需要任何其他代码,请告诉我,如果有人有兴趣自己运行代码,我也可以在 GitHub 上发布整个 AndroidStudio 项目。
谢谢!
最佳答案
由于它是随着时间的推移而构建的,因此可能意味着 View 或对象没有被操作系统正确地垃圾收集,因为它们的引用没有被释放......这会导致内存问题。我建议第一步使用内存分析器并检查在测试期间使用了多少内存。除此之外,您可以通过执行类似的操作来检查方法需要执行的时间
void methodName(){
long startTime = System.currentTimeMillis();
.
.
.
.
Log.w("time needed for this method",Long.toString(System.currentTimeMillis()-startTime);
}
关于java - Android 中的 Activity 缓慢且无响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36145181/