Android 在主线程上做了很多事情:尝试了单独的线程
Android doing to much on main thread: Tried separate threads
我遇到了断断续续的动画问题,应用程序最终崩溃了。我已经尝试分成线程,但我仍然得到在主线程中做很多事情的消息。我假设我的传感器更新和 UI 中的工作负载成正比,如果我能找到一些方法来减轻 UI 线程的负载,动画就会开始变得平滑和传感器。有没有办法让传感器侦听器脱离 UI 线程并仍然更新 UI 中的视图?
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.TextView;
public class MyActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor sensorAccelerometer;
private Sensor sensorMagneticField;
public static ImageView right;
public static ImageView left;
double pitch = 0;
double roll = 0;
public static float currentX = 0f;
public static float currentY = 0f;
public static float degreeR = 0.f;
public static float degreeL = 0.f;
public static TextView rightText;
public static TextView leftText;
public static RotateAnimation rotationLeft;
public static RotateAnimation rotationRight;
private float[] valuesAccelerometer;
private float[] valuesMagneticField;
private float[] matrixR;
private float[] matrixI;
private float[] matrixValues;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
left = (ImageView)findViewById(R.id.leftView);
right = (ImageView)findViewById(R.id.rightView);
leftText = (TextView)findViewById(R.id.leftText);
rightText = (TextView)findViewById(R.id.rightText);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
sensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
valuesAccelerometer = new float[3];
valuesMagneticField = new float[3];
matrixR = new float[9];
matrixI = new float[9];
matrixValues = new float[3];
}
@Override
public void onSensorChanged(final SensorEvent event) {
switch (event.sensor.getType()){
case Sensor.TYPE_ACCELEROMETER:
for (int i =0; i <3;i++){
valuesAccelerometer[i] = event.values[i];
}
break;
case Sensor.TYPE_MAGNETIC_FIELD:
for (int i =0;i<3;i++){
valuesMagneticField[i] = event.values[i];
}
break;
}
boolean success = SensorManager.getRotationMatrix(
matrixR,
matrixI,
valuesAccelerometer,
valuesMagneticField);
if (success){
SensorManager.getOrientation(matrixR,matrixValues);
double azimuth = Math.toDegrees(matrixValues[0]);
pitch = Math.toDegrees(matrixValues[1]);
roll = Math.toDegrees(matrixValues[2]);
}
degreeL = Math.round(roll);
degreeR = Math.round(pitch);
Thread animateL = new animateLeft();
Thread animateR = new animateRight();
animateL.run();
animateR.run();
/*Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
currentX = (-degreeR-degreeR);
currentY = ((degreeL - 90)-degreeL);///working here
}
});*/
}
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
public class animateLeft extends Thread {
@Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
MyActivity.leftText.setText("" + MyActivity.degreeL);
MyActivity.rotationRight = new RotateAnimation(
MyActivity.currentX,
MyActivity.degreeR,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
MyActivity.rotationLeft = new RotateAnimation(
MyActivity.currentY,
MyActivity.degreeL,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
MyActivity.rotationRight.setInterpolator(new LinearInterpolator());
MyActivity.rotationRight.setFillAfter(true);
MyActivity.rotationRight.setDuration(100);
MyActivity.currentY = (MyActivity.degreeL+90);
MyActivity.left.startAnimation(MyActivity.rotationLeft);
}
}
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
public class animateRight extends Thread {
@Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
MyActivity.rightText.setText("" + MyActivity.degreeR);
MyActivity.rotationLeft = new RotateAnimation(
MyActivity.currentY,
MyActivity.degreeL,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
MyActivity.rotationRight = new RotateAnimation(
MyActivity.currentX,
MyActivity.degreeR,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
MyActivity.rotationLeft.setDuration(100);
MyActivity.rotationLeft.setFillAfter(true);
MyActivity.currentX = (-MyActivity.degreeR);
MyActivity.rotationLeft.setInterpolator(new LinearInterpolator());
MyActivity.right.startAnimation(MyActivity.rotationRight);
}
}
您应该将 AsyncTask 用于此类目的。它允许您通过将其封装在 doInBackground(Params...) 方法中来在后台执行任务,完成后,您可以使用 AsyncTask [= 的 onPostExecute(Result) post UI 事件15=]。
您可以在下面阅读更多相关信息 link Async Task
有点晚了,但如果其他人还想知道,这是实现此目的的好方法。与往常一样,在多线程时,请确保您知道自己在做什么,并花时间正确处理,以避免那些奇怪的错误。玩得开心!
Class 成员:
private HandlerThread mSensorThread;
private Handler mSensorHandler;
在 OnCreate 中:
mSensorThread = new HandlerThread("Sensor thread", Thread.MAX_PRIORITY);
mSensorThread.start();
mSensorHandler = new Handler(mSensorThread.getLooper()) //Blocks until looper is prepared, which is fairly quick
yourSensorManager.registerListener(yourListener, yourSensor, interval, mSensorHandler);
注销时,也做:
mSensorThread.quitSafely();
我遇到了断断续续的动画问题,应用程序最终崩溃了。我已经尝试分成线程,但我仍然得到在主线程中做很多事情的消息。我假设我的传感器更新和 UI 中的工作负载成正比,如果我能找到一些方法来减轻 UI 线程的负载,动画就会开始变得平滑和传感器。有没有办法让传感器侦听器脱离 UI 线程并仍然更新 UI 中的视图?
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.TextView;
public class MyActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor sensorAccelerometer;
private Sensor sensorMagneticField;
public static ImageView right;
public static ImageView left;
double pitch = 0;
double roll = 0;
public static float currentX = 0f;
public static float currentY = 0f;
public static float degreeR = 0.f;
public static float degreeL = 0.f;
public static TextView rightText;
public static TextView leftText;
public static RotateAnimation rotationLeft;
public static RotateAnimation rotationRight;
private float[] valuesAccelerometer;
private float[] valuesMagneticField;
private float[] matrixR;
private float[] matrixI;
private float[] matrixValues;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
left = (ImageView)findViewById(R.id.leftView);
right = (ImageView)findViewById(R.id.rightView);
leftText = (TextView)findViewById(R.id.leftText);
rightText = (TextView)findViewById(R.id.rightText);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
sensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
valuesAccelerometer = new float[3];
valuesMagneticField = new float[3];
matrixR = new float[9];
matrixI = new float[9];
matrixValues = new float[3];
}
@Override
public void onSensorChanged(final SensorEvent event) {
switch (event.sensor.getType()){
case Sensor.TYPE_ACCELEROMETER:
for (int i =0; i <3;i++){
valuesAccelerometer[i] = event.values[i];
}
break;
case Sensor.TYPE_MAGNETIC_FIELD:
for (int i =0;i<3;i++){
valuesMagneticField[i] = event.values[i];
}
break;
}
boolean success = SensorManager.getRotationMatrix(
matrixR,
matrixI,
valuesAccelerometer,
valuesMagneticField);
if (success){
SensorManager.getOrientation(matrixR,matrixValues);
double azimuth = Math.toDegrees(matrixValues[0]);
pitch = Math.toDegrees(matrixValues[1]);
roll = Math.toDegrees(matrixValues[2]);
}
degreeL = Math.round(roll);
degreeR = Math.round(pitch);
Thread animateL = new animateLeft();
Thread animateR = new animateRight();
animateL.run();
animateR.run();
/*Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
currentX = (-degreeR-degreeR);
currentY = ((degreeL - 90)-degreeL);///working here
}
});*/
}
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
public class animateLeft extends Thread {
@Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
MyActivity.leftText.setText("" + MyActivity.degreeL);
MyActivity.rotationRight = new RotateAnimation(
MyActivity.currentX,
MyActivity.degreeR,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
MyActivity.rotationLeft = new RotateAnimation(
MyActivity.currentY,
MyActivity.degreeL,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
MyActivity.rotationRight.setInterpolator(new LinearInterpolator());
MyActivity.rotationRight.setFillAfter(true);
MyActivity.rotationRight.setDuration(100);
MyActivity.currentY = (MyActivity.degreeL+90);
MyActivity.left.startAnimation(MyActivity.rotationLeft);
}
}
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
public class animateRight extends Thread {
@Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
MyActivity.rightText.setText("" + MyActivity.degreeR);
MyActivity.rotationLeft = new RotateAnimation(
MyActivity.currentY,
MyActivity.degreeL,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
MyActivity.rotationRight = new RotateAnimation(
MyActivity.currentX,
MyActivity.degreeR,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
MyActivity.rotationLeft.setDuration(100);
MyActivity.rotationLeft.setFillAfter(true);
MyActivity.currentX = (-MyActivity.degreeR);
MyActivity.rotationLeft.setInterpolator(new LinearInterpolator());
MyActivity.right.startAnimation(MyActivity.rotationRight);
}
}
您应该将 AsyncTask 用于此类目的。它允许您通过将其封装在 doInBackground(Params...) 方法中来在后台执行任务,完成后,您可以使用 AsyncTask [= 的 onPostExecute(Result) post UI 事件15=]。
您可以在下面阅读更多相关信息 link Async Task
有点晚了,但如果其他人还想知道,这是实现此目的的好方法。与往常一样,在多线程时,请确保您知道自己在做什么,并花时间正确处理,以避免那些奇怪的错误。玩得开心!
Class 成员:
private HandlerThread mSensorThread;
private Handler mSensorHandler;
在 OnCreate 中:
mSensorThread = new HandlerThread("Sensor thread", Thread.MAX_PRIORITY);
mSensorThread.start();
mSensorHandler = new Handler(mSensorThread.getLooper()) //Blocks until looper is prepared, which is fairly quick
yourSensorManager.registerListener(yourListener, yourSensor, interval, mSensorHandler);
注销时,也做:
mSensorThread.quitSafely();