【Android应用实例之一】自动播放Assets下图片

该博客介绍了如何在Android应用中实现ImageView自动播放assets目录下的图片,每隔0.1秒切换图片,并在所有图片播放完后重新开始。关键点包括使用AssetManager读取资源,BitmapFactory处理图片,通过Handler在主线程更新UI,以及多线程和内存管理,特别是Bitmap回收以防止OutOfMemory错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载请注明出处,原文网址:http://blog.youkuaiyun.com/m_changgong/article/details/6807817  作者:张燕广

实现的功能:在ImageView中动态(每隔0.1秒)播放assets下图片,所有图片播放完毕后再重新开始播放。

实现思路:

1)通过AssetManager获取assets下资源,使用BitmapFactory将图片资源输入流转换为Bitmap对象,然后将Bitmap对象设置到ImageView组件中。

 2)动态展示图片(模拟间隔0.1秒)在子线程中操作,Android子线程是不能更新UI的,需要借助Handler(运行在主线程中)与子线程通过Message传递数据,完成更新UI的操作。

关键技术点:AssetManager应用、Bitmap对象回收技术、Handler应用、多线程及线程的终止等。

第1步:新建一个工程,命名为DisplayImagesDemo,Activity命名为DisplayImagesActivity。

第2步:往assets下拷贝几张测试用图片,然后修改main.xml文件,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical" android:layout_width="fill_parent"
	android:layout_height="fill_parent">

	<ImageView android:id="@+id/image" android:layout_width="fill_parent"
		android:layout_height="wrap_content" android:padding="5px"
		android:layout_weight="1" />
	<LinearLayout style="@android:style/ButtonBar"
		android:layout_width="fill_parent" android:layout_height="wrap_content"
		android:orientation="horizontal">
		<Button android:id="@+id/btnStart" android:text="开始播放"
			android:layout_width="0dip" android:layout_height="wrap_content"
			android:layout_weight="1" />
		<Button android:id="@+id/btnStop" android:text="停止播放"
			android:layout_width="0dip" android:layout_height="wrap_content"
			android:layout_weight="1" />
	</LinearLayout>
</LinearLayout>

第3步:修改DisplayImagesActivity,代码如下

package com.zyg.demo.assets;

import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.content.res.AssetManager;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class DisplayImagesActivity extends Activity {
	private AssetManager assets = null;
	private String[] images = null;
	private int currentImg = 0;
	private ImageView image;
	private Button btnStart;
	private Button btnStop;
	// 定义一个负责更新图片的Handler
	private Handler handler = null;
	private Thread thread = null;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		//初始化视图
		onInitView();
		//获取assets下图片
		images = getImages();
		//displayAssets();
	}

	private void onInitView(){
		image = (ImageView) findViewById(R.id.image);
		btnStart = (Button) findViewById(R.id.btnStart);
		btnStart.setOnClickListener(listener);

		btnStop = (Button) findViewById(R.id.btnStop);
		btnStop.setOnClickListener(listener);
		
		handler = new Handler() {
			public void handleMessage(android.os.Message msg) {
				// 表明消息是该程序发出的
				if (msg.what == 0x110) {
					// 展示下一张图片
					dispalyNextImage();
				}
			};
		};
	}
	
	private String[] getImages(){
		String[] tempImages = null;
		try {
			assets = getAssets();
			// 获取/assets/目录下所有文件
			if(null!=assets){
				tempImages = assets.list("");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			return tempImages;
		}
	}
	
	View.OnClickListener listener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			if (v == btnStart) {
				if(thread==null){
					thread = new Thread() {
						@Override
						public void run() {
							Thread curThread = Thread.currentThread();
							while (thread!=null && thread == curThread) {
								try {
									Thread.sleep(100);
									Message msg = new Message();
									msg.what = 0x110;
									handler.sendMessage(msg);
								} catch (InterruptedException e) {
									e.printStackTrace();
								}
							}
						}
					};
					thread.start();
				}
			} else if (v == btnStop) {
				Thread temp = thread;
				thread = null;
				temp.interrupt();
			}
		}
	};

	// 展示assets内容
	private void displayAssets() {
		int length = images.length;
		String str = null;
		for (int i = 0; i < length; i++) {
			str = images[i];
			System.out.println(i + "=" + str);
		}
	}

	// 展示下一张图片
	private void dispalyNextImage() {
		// 如果发生数组越界
		if (currentImg >= images.length) {
			currentImg = 0;
		}
		//备注1
		// 找到下一个图片文件
		while (!images[currentImg].endsWith(".png")
				&& !images[currentImg].endsWith(".jpg")
				&& !images[currentImg].endsWith(".gif")) {
			currentImg++;
			// 如果已发生数组越界
			if (currentImg >= images.length) {
				currentImg = 0;
			}
		}

		InputStream assetFile = null;
		try {
			// 打开指定资源对应的输入流
			assetFile = assets.open(images[currentImg++]);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		BitmapDrawable bitmapDrawable = (BitmapDrawable) image.getDrawable();
		//备注2
		// 如果图片还未回收,先强制回收该图片
		if (bitmapDrawable != null && !bitmapDrawable.getBitmap().isRecycled()){
			bitmapDrawable.getBitmap().recycle();
		}
		// 改变ImageView显示的图片
		image.setImageBitmap(BitmapFactory.decodeStream(assetFile));
	}
}

备注1:

之所以如此处理是因为assets下除了图片资源还有images、sounds和webkit,打开onCreate下的displayAssets()方法,可以看到输出日志。

备注2:

 如果系统频繁地去解析、创建Bitmap对象,可能由于前面创建的Bitmap所占用的内存还没有回收(手机系统本身的内容就比较小),而导致程序运行时引发OutOfMemory错误。

 事实上,如果将备注2回收Bitmap对象的语句注释掉,图片动态展示若干张(视具体情况而定,我在模拟器里运行只展示了4张就挂掉了),错误日志为:

INFO/ActivityManager(73): Low Memory: No more background processes.

第4步:运行程序,效果如下:



评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值