#android #multithreading #bitmap #handler
#Android #многопоточность #растровое изображение #обработчик
Вопрос:
У меня есть приложение, которое снимает изображение с камеры и накладывает эффект искажения «рыбий глаз» на растровое изображение. Для применения эффекта и перерисовки растрового изображения требуется более 20 секунд. я решил внедрить обработчик для ускорения обработки во втором потоке. код обработчика, похоже, не влияет на приложение. В основном, когда пользователь перемещает ползунок, это еще больше искажает растровое изображение. существует значительная задержка между перемещением ползунка и перерисовкой (). Правильно ли я это выполнил? спасибо, Мэтт.
public class TouchView extends View{
private File tempFile;
private byte[] imageArray;
private Bitmap bgr;
private Bitmap bm;
private Bitmap bgr2 = null;;
private Paint pTouch;
private int centreX = 1;
private int centreY = 1;
private int radius = 50;
private int Progress;
private static final String TAG = "*********TouchView";
private Filters f = null;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
public TouchView(Context context) {
super(context);
// TouchView(context, null);
}
public TouchView(Context context, AttributeSet attr) {
super(context,attr);
//......code that loads bitmap from sdcard
BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inSampleSize = 1;
bm = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo);
bgr = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
bgr = bm.copy(bm.getConfig(), true);
bgr2 = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
f = new Filters();
}// end of touchView constructor
public void findCirclePixels(){
Log.e(TAG, "inside fcp()");
float prog = (float)Progress/150000;
bgr2 = f.barrel(bgr,prog);
}// end of changePixel()
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
centreX = (int) ev.getX();
centreY = (int) ev.getY();
findCirclePixels();
invalidate();
break;
}
case MotionEvent.ACTION_MOVE: {
centreX = (int) ev.getX();
centreY = (int) ev.getY();
findCirclePixels();
invalidate();
break;
}
case MotionEvent.ACTION_UP:
break;
}
return true;
}//end of onTouchEvent
public void initSlider(final HorizontalSlider slider)
{
Log.e(TAG, "******setting up slider*********** ");
slider.setOnProgressChangeListener(changeListener);
}
private OnProgressChangeListener changeListener = new OnProgressChangeListener() {
@Override
public void onProgressChanged(View v, int progress) {
// TODO Auto-generated method stub
setProgress(progress);
processThread();
Log.e(TAG, "***********progress = " Progress);
}
};
private void processThread() {
new Thread() {
public void run() {
Log.e(TAG, "about to call findcirclepixel in new thread");
findCirclePixels();
handler.sendEmptyMessage(0);
}
}.start();
}
@Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawBitmap(bgr2, 0, 0, null);
}//end of onDraw
protected void setProgress(int progress2) {
this.Progress = progress2;
findCirclePixels();
invalidate();
}
}
Ответ №1:
Вы должны использовать AsyncTask . Обработчик привязан к потоку, создающему его, поэтому ваш обработчик по-прежнему привязан к потоку пользовательского интерфейса.
Комментарии:
1. Вьяс, я помню, что читал это сейчас, спасибо. Я пытался посмотреть на AsyncTask, но не уверен, как применить его к моему приложению. я опубликую другой вопрос.
Ответ №2:
Поскольку вы не предоставили весь соответствующий код, трудно получить все детали, но вот проблемы с вашим кодом, которые я смог увидеть.
- Обработчик в вашем случае следует использовать только для обновления пользовательского интерфейса после завершения операции. Фактическая работа должна выполняться в фоновом потоке, а не в обработчике.
- Вы создаете и запускаете новый поток из ProgressListener. Таким образом, вы можете столкнуться с несколькими потоками, выполняющими одну и ту же работу.
Вы можете использовать, а можете и не использовать AsyncTask
, как предлагает другой пост (хотя это хорошая идея), но используйте обработчик только для обновления пользовательского интерфейса после выполнения задания.