Урок 84. Handler. Обработка Runnable
Добавлено: 03 июн 2012, 23:00
В этом уроке:
- работаем с Handler и Runnable
Click here to read this article!
- работаем с Handler и Runnable
Click here to read this article!
Добро пожаловать на форум сайта
http://forum.startandroid.ru/
Код: Выделить всё
Thread t = new Thread(new Runnable() {
public void run() {
try {
for (cnt = 1; cnt < max; cnt++) {
TimeUnit.MILLISECONDS.sleep(100);
// обновляем ProgressBar
h.post(updateProgress);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
// обновление ProgressBar
Runnable updateProgress = new Runnable() {
public void run() {
pbCount.setProgress(cnt);
}
};
// показ информации
Runnable showInfo = new Runnable() {
public void run() {
Log.d(LOG_TAG, "showInfo");
tvInfo.setText("Count = " + cnt);
// планирует сам себя через 1000 мсек
h.postDelayed(showInfo, 1000);
}
};В этом уроке код выполняется не через прямой вызов, а через обработку сообщений. Handler h был создан в основном потоке, а значит все сообщения отправленные через него будут выполнены в основном потоке.behzodbek писал(а):а на уроке 84 изменили Активити с другого потока. А я думал тока с основного потока можно изменить Активити.
Тут путаница получается в понимании:behzodbek писал(а):а на уроке 84 изменили Активити с другого потока. А я думал тока с основного потока можно изменить Активити.
Код: Выделить всё
Runnable updateProgress = new Runnable() {
public void run() {
pbCount.setProgress(cnt);
}
};Код: Выделить всё
Runnable showInfo = new Runnable() {
public void run() {
Log.d(LOG_TAG, "showInfo");
tvInfo.setText("Count = " + cnt);
// планирует сам себя через 1000 мсек
h.postDelayed(showInfo, 1000);
}
};Код: Выделить всё
public class ImageFragment extends Fragment {
Quiz quiz;
Handler h;
Thread t;
ScaledImageView v;
int alpha;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
LinearLayout view = (LinearLayout) inflater.inflate(R.layout.quizimage, null);
v = (ScaledImageView) view.findViewById(R.id.image);
v.setBackgroundDrawable(quiz.quizData.background);
v.setImageDrawable(quiz.quizData.image);
v.setAlpha(quiz.quizData.isComplete ? 254 : 0);
return view;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
quiz = (Quiz) activity;
}
public void fadeOut(ScaledImageView v) {
h = new Handler();
t = new Thread(new Runnable() {
@Override
public void run() {
try {
for (int alpha = 0; alpha < 255; alpha++) {
TimeUnit.MILLISECONDS.sleep(10);
h.post(setAlpha);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
Runnable setAlpha = new Runnable() {
@Override
public void run() {
Log.d("mylog", "Alpha = " + alpha);
v.setAlpha(alpha);
}
};
}
Код: Выделить всё
imageFragment.fadeOut((ScaledImageView) imageFragment.getView().findViewById(R.id.image));Код: Выделить всё
Thread t = new Thread(new Runnable() {
public void run() {
try {
for (cnt = 1; cnt < max; cnt++) {
TimeUnit.MILLISECONDS.sleep(100);
// обновляем ProgressBar
h.post(updateProgress);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();Код: Выделить всё
public class MyClass extends WallpaperService {
//Вспомогательный класс для передачи в хэндлер канвы и холдера
class MyObject{
private Canvas canvas = null;
private SurfaceHolder holder = null;
MyObject(SurfaceHolder sh, Canvas cv){
canvas = cv;
holder= sh;
}
public SurfaceHolder getHolder(){return holder;}
public Canvas getCanvas(){return canvas;}
}
//Хэндлер, посылающий и обрабатывающий сообщения
private final Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
MyObject myObject= (MyObject)msg.obj;
switch(msg.what){
case 1:
Canvas c = myObject.getCanvas();
c = myObject.getHolder().lockCanvas();
break;
case 2:
myObject.getHolder().unlockCanvasAndPost(myObject.getCanvas());
break;
}
}
};
//Класс рендеринга
class WallpaperEngine extends Engine implements OnSharedPreferenceChangeListener {
.........................
private final Paint mPaint = new Paint();
private boolean mVisible = false;
private Bitmap mBitmap = null;
private Bitmap mPreviousBitmap = null;
private long mLastDrawTime = 0;
private final GestureDetector doubleTapDetector;
.........................
private final Runnable mWorker = new Runnable() {
public void run() {
if (mDuration > 0)
drawFrame();
}
};
WallpaperEngine() {
.......................
doubleTapDetector = new GestureDetector(HDLiveWallpaper.this,
new SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
if (mTouchEvents) {
mLastDrawTime = 0;
if(myThread!=null)stopThread(myThread);
drawFrame();
return true;
}
return false;
}
}
);
}
private void stopThread(MyThread thread)
{
if( myThread != null ) myThread = null;
}
.................
.................
.................
//Метод отрисовки (привожу только более менее относящееся к вопросу)
void drawFrame() {
final SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
//Получаем первое или следующее изображение для отрисовки
...................
//В случае первого входа в функцию или различных манипуляция до и после эффекта
//фиксируем канву:
c = holder.lockCanvas();
...................
c.drawColor(Color.BLACK);
c.drawBitmap(mBitmap, xPos, yPos, mPaint);
...................
if (c != null){
if((mPreviousBitmap==null) || (mPreviousBitmap==mBitmap))
holder.unlockCanvasAndPost(c);
else{
if(mTransition==1){
myThread = new MyThread(holder,c);
myThread.start();
}
else
holder.unlockCanvasAndPost(c);
}
mPreviousBitmap = mBitmap;
}
....................
mHandler.removeCallbacks(mWorker);
if (mVisible/*-если мы в фореграунде*/) {
mHandler.postDelayed(mWorker, 1000 / 2); //mWorker - это Runnable, который запускает поначалу и далее выполняет метод
//drawFrame() циклически или по требованию
}
}
//Поток с Fade-эффектом
public class MyThread extends Thread{
private SurfaceHolder _surfaceHolder;
private Canvas c;
public MyThread(SurfaceHolder holder, Canvas canvas){
_surfaceHolder = holder;
c = canvas;
}
public SurfaceHolder getHolder() { return _surfaceHolder; }
public Canvas getCanvas() { return c; }
public void run(){
c.drawBitmap(mBitmap, 0, 0, mPaint);
int tmpPaintAlpha = mPaint.getAlpha();
mPaint.setAlpha(254);
c.drawBitmap(mPreviousBitmap, 0, 0, mPaint);
//Первым делом необходимо разрочить ранее(в drawFrame()) залоченную канву
MyObject myObject = new MyObject(_surfaceHolder,c);
Message msg = mHandler.obtainMessage(2, myObject);
mHandler.sendMessage(msg); //_surfaceHolder.unlockCanvasAndPost(c);
mPaint.setAlpha(tmpPaintAlpha);
int i=253;
while(i!=0){
msg = mHandler.obtainMessage(1, myObject);
mHandler.sendMessage(msg);//c = _surfaceHolder.lockCanvas();
c.drawBitmap(mBitmap, 0, 0, mPaint);
mPaint.setAlpha(i);
c.drawBitmap(mPreviousBitmap, 0, 0, mPaint);
msg = mHandler.obtainMessage(2, myObject);
mHandler.sendMessage(msg);//_surfaceHolder.unlockCanvasAndPost(c);
mPaint.setAlpha(255);
i-=1;
}
myThread = null;
}
}
}
}
Остановить можно простым [syntax=java5]mThread = null[/syntax], приостановить [syntax=java5]mThread.interrupt()[/syntax], а запуск обычным [syntax=java5]mThread.start()[/syntax].sensetiw писал(а):Как останавливать поток и запускать заново?
Думаю он всё-таки не запускается внутри основного потока, а запускается внутри потока "message queue", который и обрабатывает всё, что приходит в хендлер.alexshr писал(а): то сразу начинает мерещиться старт нового потока. Но для этого нужен вызов start(), а в вышеприведенном коде, который и работает с view, этого нет, а есть просто метод с названием run(), который и запускается внутри основного потока