SurfaceView单线程和多线程(读写分开,信号量实现)图片切换

该博客探讨了如何在Android的SurfaceView中实现图片切换,分别展示了单线程和使用信号量实现的多线程读写分开的方法。内容包括信号量基类的介绍及应用,旨在优化图像处理的性能。
摘要由CSDN通过智能技术生成

写了一个单线程的和多线程读写分开的图片切换,多线程同步用信号量实现:

二话不说,上图:


1.信号量基类:

package com.huangcheng.sem;

public abstract class Semaphore {
	private int value = 0;

	public Semaphore() {
	}

	public Semaphore(int initial) {
		if (initial >= 0)
			value = initial;
		else
			throw new IllegalArgumentException("initial < 0");
	}

	public final synchronized void P() throws InterruptedException {
		while (value == 0)
			wait();
		value--;
	}

	protected final synchronized void Vc() {
		value++;
		notifyAll();
	}

	protected final synchronized void Vb() {
		value++;
		notifyAll();
		if (value > 1)
			value = 1;
	}

	public abstract void V();

	public String toString() {
		return ".value=" + value;
	}
}

二元信号量继承类:

package com.huangcheng.sem;

public final class BinarySemaphore extends Semaphore {
	
	public BinarySemaphore() {
		super();
	}

	public BinarySemaphore(int initial) {
		super(initial);
		if (initial > 1)
			throw new IllegalArgumentException("initial > 1");
	}

	public final synchronized void V() {
		super.Vb();
	}

}

3.Activity布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
<RelativeLayout 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/background_btn">
<Button 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="单线程"
    android:textSize="20dip"
    android:id="@+id/draw1_btn"
    android:layout_marginLeft="30dip"/>

<Button
    android:id="@+id/draw2_btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="多线程"
    android:textSize="20dip" 
    android:layout_toRightOf="@id/draw1_btn"/>
<Button
    android:id="@+id/quit_btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="退出程序"
    android:textSize="20dip" 
    android:layout_toRightOf="@id/draw2_btn"/>
</RelativeLayout>
<SurfaceView 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/surfaceview_draw"/>
</LinearLayout>
4.Activity类:

package com.huangcheng.draw;

import java.lang.reflect.Field;
import java.util.ArrayList;

import com.huangcheng.sem.BinarySemaphore;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class SurfaceViewDraw2Activity extends Activity {
	/** Called when the activity is first created. */

	private Button draw1_btn, draw2_btn,quit_btn;
	private SurfaceView surfaceview_draw;
	private SurfaceHolder surfaceholder;

	private Thread draw1_thread, prepare2_thread, draw2_thread;

	private BinarySemaphore bsem1,bsem2;

	ArrayList<Integer> imgList = new ArrayList<Integer>();
	int imgWidth, imgHeight;
	Bitmap bitmap;// 独立线程读取,独立线程绘图

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		draw1_btn = (Button) findViewById(R.id.draw1_btn);
		draw2_btn = (Button) findViewById(R.id.draw2_btn);
		quit_btn=(Button)findViewById(R.id.quit_btn);
		surfaceview_draw = (SurfaceView) findViewById(R.id.surfaceview_draw);
		surfaceholder = surfaceview_draw.getHolder();
		surfaceholder.addCallback(new DrawCallBack());

		bsem1 = new BinarySemaphore(1);
		bsem2 = new BinarySemaphore(0);
		draw1_btn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				draw1_thread.start();
			}
		});
		draw2_btn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				prepare2_thread.start();
				draw2_thread.start();
			}
		});
		quit_btn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				bitmap=null;//设置位图为null防止空指针报错
				if(!draw1_thread.isInterrupted()){
					draw1_thread.interrupt();
				}
				if(!prepare2_thread.isInterrupted()){
					prepare2_thread.interrupt();
				}
				if(!draw2_thread.isInterrupted()){
					draw2_thread.interrupt();
				}
				SurfaceViewDraw2Activity.this.finish();
			}
		});
		draw1_thread = new Thread() {
			int imgIndex = 0;
			@Override
			public void run() {
				// TODO Auto-generated method stub
				super.run();
				while (!this.isInterrupted()) {
					Canvas c = surfaceholder.lockCanvas(new Rect(0, 0,
							0 + imgWidth, 0 + imgHeight));
					Bitmap bmImg = BitmapFactory.decodeResource(getResources(),

					imgList.get(imgIndex));
					c.drawBitmap(bmImg, 0, 0, new Paint());
					imgIndex++;
					if (imgIndex == imgList.size())
						imgIndex = 0;

					surfaceholder.unlockCanvasAndPost(c);// 更新屏幕显示内容
					ClearDraw(0, 0, imgWidth, imgHeight);
				}
			}
		};
		prepare2_thread = new Thread() {
			int imgIndex = 0;

			@Override
			public void run() {
				// TODO Auto-generated method stub
				super.run();
				while (!this.isInterrupted()) {
					try {
						bsem1.P();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					bitmap = BitmapFactory.decodeResource(getResources(),
							imgList.get(imgIndex));
					imgIndex++;
					System.out.println("imgIndex:"+imgIndex);
					if (imgIndex == imgList.size())
						imgIndex = 0;
					bsem2.V();
				}
			}
		};
		draw2_thread = new Thread() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				super.run();
				while (!this.isInterrupted()) {
					try {
						bsem2.P();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					Canvas c = surfaceholder.lockCanvas(new Rect(0, imgHeight,
							0 + imgWidth, 0 + imgHeight));
					if(bitmap!=null){
						c.drawBitmap(bitmap, 0, imgHeight, new Paint());
					}
					System.out.println("bitmap:");
					surfaceholder.unlockCanvasAndPost(c);
					ClearDraw(0, imgHeight, imgWidth, imgHeight);
					bsem1.V();
				}
			}
		};
	}

	class DrawCallBack implements SurfaceHolder.Callback {

		@Override
		public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
				int arg3) {
			// TODO Auto-generated method stub
			Log.i("Surface:","Change");
		}

		@Override
		public void surfaceCreated(SurfaceHolder arg0) {
			// TODO Auto-generated method stub
			Log.i("Surface:", "Create");

			// 用反射机制来获取资源中的图片 ID 和尺寸
			Field[] fields = R.drawable.class.getDeclaredFields();
			for (Field field : fields) {
				if (!"ic_laucher".equals(field.getName())) {
					int index = 0;
					try {
						index = field.getInt(R.drawable.class);
					} catch (IllegalArgumentException e) {
						// TODO Auto‐generated catch block
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						// TODO Auto‐generated catch block
						e.printStackTrace();
					}
					// 保存图片 ID
					imgList.add(index);
				}
			}
			Bitmap bmImg = BitmapFactory.decodeResource(getResources(),
					imgList.get(0));
			imgWidth = bmImg.getWidth();
			imgHeight = bmImg.getHeight();
		}

		@Override
		public void surfaceDestroyed(SurfaceHolder arg0) {
			// TODO Auto-generated method stub
			Log.i("Surface:","Destory");
		}
	}
	// 消除画得图
	private synchronized void ClearDraw(int x1,int y1,int x2,int y2) {
		Canvas canvas = surfaceholder.lockCanvas(new Rect(x1, y1, x2, y2));
		canvas.drawColor(Color.BLACK);// 清除画布
		surfaceholder.unlockCanvasAndPost(canvas);
	}
}
欢迎大家拍砖~~~~~~~~~~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值