当前位置:  编程技术>移动开发
本页文章导读:
    ▪转:AsyncTask 以致FC 研究        转:AsyncTask 导致FC 研究 导语:在开发Android应用的过程中,我们需要时刻注意保障应用的稳定性和界面响应性,因为不稳定或者响应速度慢的应用将会给用户带来非常差的交互体验。在越.........
    ▪ 关于 apk资料反编译的方法(dex2jar和JD-GUI)        关于 apk文件反编译的方法(dex2jar和JD-GUI) 觉着这2个工具配合学习android太靠谱了,所以放上来给大家共享,开源的好处就是好东西大家一起分享;1.首先找到Android软件安装包中的class.dex     把apk.........
    ▪ requestWindowFeature应用详解       requestWindowFeature使用详解 requestWindowFeature可以设置的值有: // 1.DEFAULT_FEATURES:系统默认状态,一般不需要指定        // 2.FEATURE_CONTEXT_MENU:启用ContextMenu,默认该项已启用,一般无需指定.........

[1]转:AsyncTask 以致FC 研究
    来源: 互联网  发布时间: 2014-02-18
转:AsyncTask 导致FC 研究

导语:在开发Android应用的过程中,我们需要时刻注意保障应用的稳定性和界面响应性,因为不稳定或者响应速度慢的应用将会给用户带来非常差的交互体验。在越来越讲究用户体验的大环境下,用户也许会因为应用的一次Force Close(简称FC)或者延迟严重的动画效果而卸载你的应用。由于现在的应用大多需要异步连接网络,本系列文章就以构建网络应用为例,从稳定性和响应性两个角度分析多线程网络任务的性能优化方法。

 

概述:为了不阻塞UI线程(亦称主线程),提高应用的响应性,我们经常会使用新开线程的方式,异步处理那些导致阻塞的任务(如要了解Android异步处理的实现方式和原理,请先阅读《Android异步处理系列文章索引》)。

AsyncTask是Android为我们提供的方便编写异步任务的工具类,但是,在了解AsyncTask的实现原理之后,发现AsyncTask并不能满足我们所有的需求,使用不当还有可能导致应用FC。

本文主要通过分析AsyncTask提交任务的策略和一个具体的例子,说明AsyncTask的不足之处,至于解决办法,我们将在下篇再讲解。

分析:

AsyncTask类包含一个全局静态的线程池,线程池的配置参数如下:

  • private static final int CORE_POOL_SIZE =5;//5个核心工作线程   
  •    private static final int MAXIMUM_POOL_SIZE = 128;//最多128个工作线程   
  •    private static final int KEEP_ALIVE = 1;//空闲线程的超时时间为1秒   
  •    
  •    private static final BlockingQueue<Runnable> sWorkQueue =  
  •            new LinkedBlockingQueue<Runnable>(10);//等待队列   
  •    
  •    private static final ThreadPoolExecutorsExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,  
  •            MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue,sThreadFactory);//线程池是静态变量,所有的异步任务都会放到这个线程池的工作线程内执行。  
  •  

    我们这里不详细讲解ThreadPoolExecutor的原理,但将会讲解一个异步任务提交到AsyncTask的线程池时可能会出现的4种情况,并会提出在Android硬件配置普遍较低这个客观条件下,每个情况可能会出现的问题。

    1、线程池中的工作线程少于5个时,将会创建新的工作线程执行异步任务(红色表示新任务,下同)

    2、线程池中已经有5个线程,缓冲队列未满,异步任务将会放到缓冲队列中等待

    3、线程池中已经有5个线程,缓冲队列已满,那么线程池将新开工作线程执行异步任务

    问题:Android的设备一般不超过2个cpu核心,过多的线程会造成线程间切换频繁,消耗系统资源。

    4、线程池中已经有128个线程,缓冲队列已满,如果此时向线程提交任务,将会抛出RejectedExecutionException

    问题:抛出的错误不catch的话会导致程序FC。

     

    好吧,理论分析之后还是要结合实际例子,我们通过实现一个模拟异步获取网络图片的例子,看看会不会出现上面提到的问题。

     

    例子:使用GridView模拟异步加载大量图片

    ActivityA.java

  • package com.zhuozhuo;  
  •   
  • import java.util.ArrayList;  
  • import java.util.Collection;  
  • import java.util.HashMap;  
  • import java.util.Iterator;  
  • import java.util.List;  
  • import java.util.ListIterator;  
  • import java.util.Map;  
  •   
  •   
  • import Android.app.Activity;  
  • import Android.app.AlertDialog;  
  • import Android.app.Dialog;  
  • import Android.app.ListActivity;  
  • import Android.app.ProgressDialog;  
  • import Android.content.Context;  
  • import Android.content.DialogInterface;  
  • import Android.content.Intent;  
  • import Android.database.Cursor;  
  • import Android.graphics.Bitmap;  
  • import Android.os.AsyncTask;  
  • import Android.os.Bundle;  
  • import Android.provider.ContactsContract;  
  • import Android.util.Log;  
  • import Android.view.LayoutInflater;  
  • import Android.view.View;  
  • import Android.view.ViewGroup;  
  • import Android.widget.AbsListView;  
  • import Android.widget.AbsListView.OnScrollListener;  
  • import Android.widget.Adapter;  
  • import Android.widget.AdapterView;  
  • import Android.widget.AdapterView.OnItemClickListener;  
  • import Android.widget.BaseAdapter;  
  • import Android.widget.GridView;  
  • import Android.widget.ImageView;  
  • import Android.widget.ListAdapter;  
  • import Android.widget.SimpleAdapter;  
  • import Android.widget.TextView;  
  • import Android.widget.Toast;  
  •   
  • public class ActivityA extends Activity {  
  •       
  •       
  •     private GridView mGridView;  
  •     private List<HashMap<String, Object>> mData;  
  •       
  •     private BaseAdapter mAdapter;  
  •     private ProgressDialog mProgressDialog;  
  •       
  •     private static final int DIALOG_PROGRESS = 0;  
  •       
  •     @Override  
  •     public void onCreate(Bundle savedInstanceState) {  
  •         super.onCreate(savedInstanceState);  
  •         setContentView(R.layout.main);  
  •         mGridView = (GridView) findViewById(R.id.gridview);  
  •         mData = new ArrayList<HashMap<String,Object>>();  
  •         mAdapter = new CustomAdapter();  
  •           
  •          
  •         mGridView.setAdapter(mAdapter);  
  •     }  
  •       
  •     protected void onStart () {  
  •         super.onStart();  
  •         new GetGridDataTask().execute(null);//执行获取数据的任务   
  •     }  
  •       
  •       
  •       
  •       
  •     @Override  
  •     protected Dialog onCreateDialog(int id) {  
  •         switch (id) {  
  •         case DIALOG_PROGRESS:  
  •             mProgressDialog = new ProgressDialog(ActivityA.this);  
  •             mProgressDialog.setMessage("正在获取数据");  
  •             mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);  
  •   
  •             return mProgressDialog;  
  •   
  •          
  •         }  
  •         return null;  
  •     }  
  •   
  •     class CustomAdapter extends BaseAdapter {  
  •   
  •           
  •         CustomAdapter() {  
  •               
  •         }  
  •           
  •         @Override  
  •         public int getCount() {  
  •             return mData.size();  
  •         }  
  •   
  •         @Override  
  •         public Object getItem(int position) {  
  •             return mData.get(position);  
  •         }  
  •   
  •         @Override  
  •         public long getItemId(int position) {  
  •             return 0;  
  •         }  
  •   
  •         @Override  
  •         public View getView(int position, View convertView, ViewGroup parent) {  
  •             View view = convertView;  
  •             ViewHolder vh;  
  •             if(view == null) {  
  •                 view = LayoutInflater.from(ActivityA.this).inflate(R.layout.list_item, null);  
  •                 vh = new ViewHolder();  
  •                 vh.tv = (TextView) view.findViewById(R.id.textView);  
  •                 vh.iv = (ImageView) view.findViewById(R.id.imageView);  
  •                 view.setTag(vh);  
  •             }  
  •             vh = (ViewHolder) view.getTag();  
  •             vh.tv.setText((String) mData.get(position).get("title"));  
  •             Integer id = (Integer) mData.get(position).get("pic");  
  •             if(id != null) {  
  •                 vh.iv.setImageResource(id);  
  •             }  
  •             else {  
  •                 vh.iv.setImageBitmap(null);  
  •             }  
  •               
  •             FifoAsyncTask task = (FifoAsyncTask) mData.get(position).get("task");  
  •             if(task == null || task.isCancelled()) {  
  •                 Log.d("Test", "" + position);  
  •                 mData.get(position).put("task", new GetItemImageTask(position).execute(null));//执行获取图片的任务   
  •             }  
  •               
  •             return view;  
  •         }  
  •   
  •           
  •           
  •     }  
  •       
  •     static class ViewHolder {  
  •         TextView tv;  
  •         ImageView iv;  
  •     }  
  •       
  •     class GetGridDataTask extends FifoAsyncTask<Void, Void, Void> {  
  •           
  •         protected void onPreExecute () {  
  •             mData.clear();  
  •             mAdapter.notifyDataSetChanged();  
  •               
  •             showDialog(DIALOG_PROGRESS);//打开等待对话框   
  •         }  
  •           
  •         @Override  
  •         protected Void doInBackground(Void... params) {  
  •               
  •             try {  
  •                 Thread.sleep(500);//模拟耗时的网络操作   
  •             } catch (InterruptedException e) {  
  •                 e.printStackTrace();  
  •             }  
  •             for(int i = 0; i < 200; i++) {  
  •                 HashMap<String, Object> hm = new HashMap<String, Object>();  
  •                 hm.put("title", "Title");  
  •                 mData.add(hm);  
  •             }  
  •               
  •             return null;  
  •         }  
  •           
  •         protected void onPostExecute (Void result) {  
  •             mAdapter.notifyDataSetChanged();//通知ui界面更新   
  •             dismissDialog(DIALOG_PROGRESS);//关闭等待对话框   
  •         }  
  •           
  •     }  
  •       
  •     class GetItemImageTask extends FifoAsyncTask<Void, Void, Void> {  
  •           
  •         int pos;  
  •           
  •         GetItemImageTask(int pos) {  
  •             this.pos = pos;  
  •         }  
  •   
  •         @Override  
  •         protected Void doInBackground(Void... params) {  
  •             try {  
  •                 Thread.sleep(2000); //模拟耗时的网络操作   
  •             } catch (InterruptedException e) {  
  •                 e.printStackTrace();  
  •             }  
  •             mData.get(pos).put("pic", R.drawable.icon);  
  •             return null;  
  •         }  
  •           
  •         protected void onPostExecute (Void result) {  
  •             mAdapter.notifyDataSetChanged();//通知ui界面更新   
  •         }  
  •           
  •     }  
  •   
  • }  
  •  


     

    由运行图可见

    当网络情况较差,异步任务不能尽快完成执行的情况下,新开的线程会造成listview滑动不流畅。当开启的工作线程过多时,还有出现FC的可能。

    至此,你还相信万能的AsyncTask吗?至于你信不信,反正我不信。

    总结:

    AsyncTask可能存在新开大量线程消耗系统资源和导致应用FC的风险,因此,我们需要根据自己的需求自定义不同的线程池,由于篇幅问题,将留到下篇再讲。


     


        
    [2] 关于 apk资料反编译的方法(dex2jar和JD-GUI)
        来源: 互联网  发布时间: 2014-02-18
    关于 apk文件反编译的方法(dex2jar和JD-GUI)

    觉着这2个工具配合学习android太靠谱了,所以放上来给大家共享,开源的好处就是好东西大家一起分享;
    1.首先找到Android软件安装包中的class.dex
        把apk文件改名为.zip,然后解压缩其中的class.dex文件,它就是java文件编译再通过dx工具打包成的,所以现在我们就用上述提到的2个工具来逆方向导出java源文件;
    2.把class.dex拷贝到dex2jar.bat所在目录。 (http://www.my400800.cn )
        运行dex2jar.bat classes.dex

       生成classes_dex2jar.jar
    3.运行JD-GUI工具(它是绿色无须安装的)
        打开上面的jar文件,即可看到源代码
        俺也是今天才试验了下效果,那是相当的凑效,所以兄弟姐妹们觉着好就给句鼓励的话

     

     

    4 用AXMLPrinter反编译xml文件:

        java -jar AXMLPrinter2.jar AndroidManifest.xml -> AndroidManifest2.xml

        AXMLPrinter的下载地址如下:

        http://android4me.googlecode.com/files/AXMLPrinter2.jar

     

     

     

    dex2jar 下载

     

     

    JD-GUI 下载

     

    AXMLPrinter2.jar 下载

     

     


        
    [3] requestWindowFeature应用详解
        来源: 互联网  发布时间: 2014-02-18
    requestWindowFeature使用详解

    requestWindowFeature可以设置的值有:
     // 1.DEFAULT_FEATURES:系统默认状态,一般不需要指定
            // 2.FEATURE_CONTEXT_MENU:启用ContextMenu,默认该项已启用,一般无需指定
            // 3.FEATURE_CUSTOM_TITLE:自定义标题。当需要自定义标题时必须指定。如:标题是一个按钮时
            // 4.FEATURE_INDETERMINATE_PROGRESS:不确定的进度
            // 5.FEATURE_LEFT_ICON:标题栏左侧的图标
            // 6.FEATURE_NO_TITLE:无标题
            // 7.FEATURE_OPTIONS_PANEL:启用“选项面板”功能,默认已启用。
            // 8.FEATURE_PROGRESS:进度指示器功能
            // 9.FEATURE_RIGHT_ICON:标题栏右侧的图标

    效果图:
     default:

     
     progress:


    no title:



     
     lefticon:



     fullscreen:

     indeterminate_progress:

     

    customtitle:



     

     

    代码:
    package com.my;

    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.Window;
    import android.view.WindowManager;

    public class WindowFeatureDemoActivity extends Activity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // requestWindowFeature();的取值
            // 1.DEFAULT_FEATURES:系统默认状态,一般不需要指定
            // 2.FEATURE_CONTEXT_MENU:启用ContextMenu,默认该项已启用,一般无需指定
            // 3.FEATURE_CUSTOM_TITLE:自定义标题。当需要自定义标题时必须指定。如:标题是一个按钮时
            // 4.FEATURE_INDETERMINATE_PROGRESS:不确定的进度
            // 5.FEATURE_LEFT_ICON:标题栏左侧的图标
            // 6.FEATURE_NO_TITLE:无标题
            // 7.FEATURE_OPTIONS_PANEL:启用“选项面板”功能,默认已启用。
            // 8.FEATURE_PROGRESS:进度指示器功能
            // 9.FEATURE_RIGHT_ICON:标题栏右侧的图标
            // ========================FEATURE_INDETERMINATE_PROGRESS:不确定的进度
    //        showFEATURE_INDETERMINATE_PROGRESS();
    //        // =====================FEATURE_CUSTOM_TITLE      
    //        showFEATURE_CUSTOM_TITLE();
    //        // ======================== FEATURE_LEFT_ICON:标题栏左侧的图标
    //        showFEATURE_LEFT_ICON();
    //        // ======================FEATURE_NO_TITLE
    //        showFEATURE_NO_TITLE();  
    //         =================================FEATURE_PROGRESS
            showFEATURE_PROGRESS();

        }

        private void showFEATURE_INDETERMINATE_PROGRESS() {
            requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
            setContentView(R.layout.main);
            getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS, R.layout.progress);
            // 必须得加上否则显示不出效果 可以通过这个在以后设置显示或隐藏
            setProgressBarIndeterminateVisibility(true);
        }

        private void showFEATURE_CUSTOM_TITLE() {
            // 自定义标题。当需要自定义标题时必须指定。如:标题是一个按钮时
            requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
            setContentView(R.layout.main);
            getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.customtitle);
        }
        private void showFEATURE_LEFT_ICON()
        {
             requestWindowFeature(Window.FEATURE_LEFT_ICON);
             setContentView(R.layout.main);
             getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
             R.drawable.icon);
        }
        private void showFEATURE_NO_TITLE()
        {
             requestWindowFeature(Window.FEATURE_NO_TITLE);
             setContentView(R.layout.main);
             // 加上这句设置为全屏 不加则只隐藏title
             getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
             WindowManager.LayoutParams.FLAG_FULLSCREEN);
        }
        private void showFEATURE_PROGRESS()
        {
            requestWindowFeature(Window.FEATURE_PROGRESS);
            setProgressBarVisibility(true);
            setContentView(R.layout.main);
            setTitle("");
            getWindow().setFeatureInt(Window.FEATURE_PROGRESS, Window.PROGRESS_VISIBILITY_ON);
            // 通过线程来改变ProgressBar的值
            new Thread(new Runnable() {
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        try {
                            Thread.sleep(1000);
                            Message m = new Message();
                            m.what = (i + 1) * 20;
                            WindowFeatureDemoActivity.this.myMessageHandler.sendMessage(m);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }
        Handler myMessageHandler = new Handler() {
            // @Override
            public void handleMessage(Message msg) {

                // 设置标题栏中前景的一个进度条进度值
                setProgress(100 * msg.what);
                // 设置标题栏中后面的一个进度条进度值
                setSecondaryProgress(100 * msg.what + 10);
                super.handleMessage(msg);
            }
        };

    }


        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    ▪Android实现退出时关闭所有Activity的方法
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android获取当前已连接的wifi信号强度的方法
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android提高之自定义Menu(TabMenu)实现方法
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    jquery iis7站长之家
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3