• 配置项发生改变时保持程序状态


    在我们进行Android项目开发时,经常会遇到一个问题,如何保持程序的一些运行状态。比如当前的Activity正在下载一张图片,突然设备横竖屏切换(Activity会重新create),之前的下载线程可能并没有完成,这时如何来复用之前的下载线程呢,这是就需要把之前的下载线程保存起来

     
         Android SDK对这种功能提供了支持,API 13之前可以通过 getLastNonConfigurationInstance()   获得保存的对象实例通 onRetainNonConfigurationInstance ()   回调方法来保存一个对象实例,但这种机制在API 13被废弃了,下面是一个demo
     
    package de.vogella.android.threadslifecycle;
    
    import java.io.IOException;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.StatusLine;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpUriRequest;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.util.EntityUtils;
    
    import android.app.Activity;
    import android.app.ProgressDialog;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.View;
    import android.widget.ImageView;
    
    public class ThreadsLifecycleActivity extends Activity {
      // Static so that the thread access the latest attribute
      private static ProgressDialog dialog;
      private static Bitmap downloadBitmap;
      private static Handler handler;
      private ImageView imageView;
      private Thread downloadThread;
    
      
    
    /** Called when the activity is first created. */
    
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // Create a handler to update the UI
        handler = new Handler() {
          @Override
          public void handleMessage(Message msg) {
            imageView.setImageBitmap(downloadBitmap);
            dialog.dismiss();
          }
    
        };
        // get the latest imageView after restart of the application
        imageView = (ImageView) findViewById(R.id.imageView1);
        Context context = imageView.getContext();
        System.out.println(context);
        // Did we already download the image?
        if (downloadBitmap != null) {
          imageView.setImageBitmap(downloadBitmap);
        }
        // Check if the thread is already running
        downloadThread = (Thread) getLastNonConfigurationInstance();
        if (downloadThread != null && downloadThread.isAlive()) {
          dialog = ProgressDialog.show(this, "Download", "downloading");
        }
      }
    
      public void resetPicture(View view) {
        if (downloadBitmap != null) {
          downloadBitmap = null;
        }
        imageView.setImageResource(R.drawable.icon);
      }
    
      public void downloadPicture(View view) {
        dialog = ProgressDialog.show(this, "Download", "downloading");
        downloadThread = new MyThread();
        downloadThread.start();
      }
    
      // Save the thread
      @Override
      public Object onRetainNonConfigurationInstance() {
        return downloadThread;
      }
    
      // dismiss dialog if activity is destroyed
      @Override
      protected void onDestroy() {
        if (dialog != null && dialog.isShowing()) {
          dialog.dismiss();
          dialog = null;
        }
        super.onDestroy();
      }
    
      // Utiliy method to download image from the internet
      static private Bitmap downloadBitmap(String url) throws IOException {
        HttpUriRequest request = new HttpGet(url);
        HttpClient httpClient = new DefaultHttpClient();
        HttpResponse response = httpClient.execute(request);
    
        StatusLine statusLine = response.getStatusLine();
        int statusCode = statusLine.getStatusCode();
        if (statusCode == 200) {
          HttpEntity entity = response.getEntity();
          byte[] bytes = EntityUtils.toByteArray(entity);
    
          Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0,
              bytes.length);
          return bitmap;
        } else {
          throw new IOException("Download failed, HTTP response code "
              + statusCode + " - " + statusLine.getReasonPhrase());
        }
      }
    
      static public class MyThread extends Thread {
        @Override
        public void run() {
          try {
            // Simulate a slow network
            try {
              new Thread().sleep(5000);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
            downloadBitmap = downloadBitmap("http://www.devoxx.com/download/attachments/4751369/DV11");
            // Updates the user interface
            handler.sendEmptyMessage(0);
          } catch (IOException e) {
            e.printStackTrace();
          } finally {
    
          }
        }
      }
    
    } 
    

    在模拟器中可以通过ctrl+11来看效果,以上代码可以在  http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html#fragmentsandbackgroundprocessing  上找到

         API 13 推荐使用Fragment来替代,通过设置 setRetainInstance(   true  );  使Fragment在设备配置改变后(比如横竖屏切换)Activity重新创建时还能够获取到,具体介绍可以去看下Fragment的说明 ,下面是一个简单的实现(代码提取自BitmapFun项目)
    package com.activity.lifecycle.threads;
    
    import android.annotation.TargetApi;
    import android.app.Activity;
    import android.app.Fragment;
    import android.app.FragmentManager;
    import android.os.Build;
    import android.os.Bundle;
    import android.widget.TextView;
    
    public class TestActivity extends Activity {
    
            private static final String TAG = "TestActivity" ;
           
            @TargetApi (Build.VERSION_CODES. HONEYCOMB)
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                  super .onCreate(savedInstanceState);
                 
                 TextView tv = new TextView( this);
                 tv.setText( "this is the second activity" );
                 setContentView(tv);
                 
            // Search for, or create an instance of the non-UI RetainFragment
            final RetainFragment mRetainFragment = findOrCreateRetainFragment(getFragmentManager());
    
            // See if we already have an ImageCache stored in RetainFragment
            Thread thread = (Thread) mRetainFragment.getObject();
    
    //         No existing ImageCache, create one and store it in RetainFragment
            if (thread == null) {
                 thread = new Thread() ;
                mRetainFragment.setObject(thread);
            }
                 
            // TODO
           }
    
        /**
         * Locate an existing instance of this Fragment or if not found, create and
         * add it using FragmentManager.
         *
         * @param fm The FragmentManager manager to use.
         * @return The existing instance of the Fragment or the new instance if just
         *         created.
         */
            @TargetApi (Build.VERSION_CODES. HONEYCOMB)
            private static RetainFragment findOrCreateRetainFragment(FragmentManager fm) {
            // Check to see if we have retained the worker fragment.
            RetainFragment mRetainFragment = (RetainFragment)fm.findFragmentByTag(TAG );
    
            // If not retained (or first time running), we need to create and add it.
            if (mRetainFragment == null) {
                mRetainFragment = new RetainFragment();
                fm.beginTransaction().add(mRetainFragment, TAG ).commitAllowingStateLoss();
            }
    
            return mRetainFragment;
        }
       
        /**
         * A simple non - UI Fragment that stores a single Object and is retained over configuration
         * changes. It will be used to retain the ImageCache object.
         */
        public static class RetainFragment extends Fragment {
            private Object mObject ;
    
            /**
             * Empty constructor as per the Fragment documentation
             */
            public RetainFragment() {}
    
            @TargetApi (Build.VERSION_CODES. HONEYCOMB)
                  @Override
            public void onCreate(Bundle savedInstanceState) {
                super .onCreate(savedInstanceState);
    
                // Make sure this Fragment is retained over a configuration change
                setRetainInstance( true );
            }
    
            /**
             * Store a single object in this Fragment.
             *
             * @param object The object to store
             */
            public void setObject(Object object) {
                mObject = object;
            }
    
            /**
             * Get the stored object.
             *
             * @return The stored object
             */
            public Object getObject() {
                return mObject ;
            }
        }
    }
    

    因为API 13才开始提供,所以之前的版本可以使用Android提供的兼容包来支持







  • 相关阅读:
    批量替换文本的工具
    wcf异常显示错误到客户端
    文件以二进制存入数据库和从数据库读取二进制文件
    关于关系数据库的范式
    对于挑战书上的很久之前都看不懂的DP看懂的突破
    操作系统概念
    关于P,V操作理解的突破,关于并发设计与并行
    关于快速沃尔什变换
    我觉得我应该养成经常翻收藏夹的习惯
    目前我的思考模式
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3180117.html
Copyright © 2020-2023  润新知