Android应用实例之动态展示assets下图片


实现的功能:在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文件,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical" android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent">  
  5.   
  6.     <ImageView android:id="@+id/image" android:layout_width="fill_parent"  
  7.         android:layout_height="wrap_content" android:padding="5px"  
  8.         android:layout_weight="1" />  
  9.     <LinearLayout style="@android:style/ButtonBar"  
  10.         android:layout_width="fill_parent" android:layout_height="wrap_content"  
  11.         android:orientation="horizontal">  
  12.         <Button android:id="@+id/btnStart" android:text="开始播放"  
  13.             android:layout_width="0dip" android:layout_height="wrap_content"  
  14.             android:layout_weight="1" />  
  15.         <Button android:id="@+id/btnStop" android:text="停止播放"  
  16.             android:layout_width="0dip" android:layout_height="wrap_content"  
  17.             android:layout_weight="1" />  
  18.     </LinearLayout>  
  19. </LinearLayout>  

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

  1. package com.zyg.demo.assets;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import android.app.Activity;  
  6. import android.content.res.AssetManager;  
  7. import android.graphics.BitmapFactory;  
  8. import android.graphics.drawable.BitmapDrawable;  
  9. import android.os.Bundle;  
  10. import android.os.Handler;  
  11. import android.os.Message;  
  12. import android.view.View;  
  13. import android.view.View.OnClickListener;  
  14. import android.widget.Button;  
  15. import android.widget.ImageView;  
  16.   
  17. public class DisplayImagesActivity extends Activity {  
  18.     private AssetManager assets = null;  
  19.     private String[] images = null;  
  20.     private int currentImg = 0;  
  21.     private ImageView image;  
  22.     private Button btnStart;  
  23.     private Button btnStop;  
  24.     // 定义一个负责更新图片的Handler   
  25.     private Handler handler = null;  
  26.     private Thread thread = null;  
  27.     @Override  
  28.     public void onCreate(Bundle savedInstanceState) {  
  29.         super.onCreate(savedInstanceState);  
  30.         setContentView(R.layout.main);  
  31.         //初始化视图   
  32.         onInitView();  
  33.         //获取assets下图片   
  34.         images = getImages();  
  35.         //displayAssets();   
  36.     }  
  37.   
  38.     private void onInitView(){  
  39.         image = (ImageView) findViewById(R.id.image);  
  40.         btnStart = (Button) findViewById(R.id.btnStart);  
  41.         btnStart.setOnClickListener(listener);  
  42.   
  43.         btnStop = (Button) findViewById(R.id.btnStop);  
  44.         btnStop.setOnClickListener(listener);  
  45.           
  46.         handler = new Handler() {  
  47.             public void handleMessage(android.os.Message msg) {  
  48.                 // 表明消息是该程序发出的   
  49.                 if (msg.what == 0x110) {  
  50.                     // 展示下一张图片   
  51.                     dispalyNextImage();  
  52.                 }  
  53.             };  
  54.         };  
  55.     }  
  56.       
  57.     private String[] getImages(){  
  58.         String[] tempImages = null;  
  59.         try {  
  60.             assets = getAssets();  
  61.             // 获取/assets/目录下所有文件   
  62.             if(null!=assets){  
  63.                 tempImages = assets.list("");  
  64.             }  
  65.         } catch (IOException e) {  
  66.             e.printStackTrace();  
  67.         }finally{  
  68.             return tempImages;  
  69.         }  
  70.     }  
  71.       
  72.     View.OnClickListener listener = new OnClickListener() {  
  73.         @Override  
  74.         public void onClick(View v) {  
  75.             if (v == btnStart) {  
  76.                 if(thread==null){  
  77.                     thread = new Thread() {  
  78.                         @Override  
  79.                         public void run() {  
  80.                             Thread curThread = Thread.currentThread();  
  81.                             while (thread!=null && thread == curThread) {  
  82.                                 try {  
  83.                                     Thread.sleep(100);  
  84.                                     Message msg = new Message();  
  85.                                     msg.what = 0x110;  
  86.                                     handler.sendMessage(msg);  
  87.                                 } catch (InterruptedException e) {  
  88.                                     e.printStackTrace();  
  89.                                 }  
  90.                             }  
  91.                         }  
  92.                     };  
  93.                     thread.start();  
  94.                 }  
  95.             } else if (v == btnStop) {  
  96.                 Thread temp = thread;  
  97.                 thread = null;  
  98.                 temp.interrupt();  
  99.             }  
  100.         }  
  101.     };  
  102.   
  103.     // 展示assets内容   
  104.     private void displayAssets() {  
  105.         int length = images.length;  
  106.         String str = null;  
  107.         for (int i = 0; i < length; i++) {  
  108.             str = images[i];  
  109.             System.out.println(i + "=" + str);  
  110.         }  
  111.     }  
  112.   
  113.     // 展示下一张图片   
  114.     private void dispalyNextImage() {  
  115.         // 如果发生数组越界   
  116.         if (currentImg >= images.length) {  
  117.             currentImg = 0;  
  118.         }  
  119.         //备注1   
  120.         // 找到下一个图片文件   
  121.         while (!images[currentImg].endsWith(".png")  
  122.                 && !images[currentImg].endsWith(".jpg")  
  123.                 && !images[currentImg].endsWith(".gif")) {  
  124.             currentImg++;  
  125.             // 如果已发生数组越界   
  126.             if (currentImg >= images.length) {  
  127.                 currentImg = 0;  
  128.             }  
  129.         }  
  130.   
  131.         InputStream assetFile = null;  
  132.         try {  
  133.             // 打开指定资源对应的输入流   
  134.             assetFile = assets.open(images[currentImg++]);  
  135.         } catch (IOException e) {  
  136.             e.printStackTrace();  
  137.         }  
  138.           
  139.         BitmapDrawable bitmapDrawable = (BitmapDrawable) image.getDrawable();  
  140.         //备注2   
  141.         // 如果图片还未回收,先强制回收该图片   
  142.         if (bitmapDrawable != null && !bitmapDrawable.getBitmap().isRecycled()){  
  143.             bitmapDrawable.getBitmap().recycle();  
  144.         }  
  145.         // 改变ImageView显示的图片   
  146.         image.setImageBitmap(BitmapFactory.decodeStream(assetFile));  
  147.     }  
  148. }  

备注1:

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

备注2:

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

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

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

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

相关内容