首页 > 代码库 > Android开发中使用static变量应该注意的问题

Android开发中使用static变量应该注意的问题

  1 package com.highxin.launcher01;  2   3   4   5 import java.util.ArrayList;  6 import java.util.HashMap;  7 import java.util.Iterator;  8 import java.util.List;  9 import java.util.Map; 10  11 import android.app.Activity; 12 import android.content.ComponentName; 13 import android.content.ContentResolver; 14 import android.content.Context; 15 import android.content.Intent; 16 import android.content.pm.ApplicationInfo; 17 import android.content.pm.PackageInfo; 18 import android.content.pm.PackageManager; 19 import android.content.pm.ResolveInfo; 20 import android.database.Cursor; 21 import android.graphics.drawable.Drawable; 22 import android.net.Uri; 23 import android.os.Bundle; 24 import android.os.Handler; 25 import android.os.Message; 26 import android.provider.ContactsContract; 27 import android.provider.ContactsContract.CommonDataKinds; 28 import android.provider.ContactsContract.PhoneLookup; 29 import android.provider.MediaStore; 30 import android.util.Log; 31 import android.view.KeyEvent; 32 import android.view.LayoutInflater; 33 import android.view.View; 34 import android.view.ViewGroup; 35 import android.view.Window; 36 import android.widget.AdapterView; 37 import android.widget.AdapterView.OnItemClickListener; 38 import android.widget.BaseAdapter; 39 import android.widget.GridView; 40 import android.widget.ImageView; 41 import android.widget.TextView; 42  43 public class MainActivity extends Activity implements Runnable,OnItemClickListener{ 44     String name = ""; 45     String phoneNO = ""; 46     public static  List<Map<String, Object>>  contacts_list = new ArrayList<Map<String, Object>>(); 47     public static  List<Map<String, Object>>  gv_applist = new ArrayList<Map<String,Object>>(); 48     public static boolean switch_flag = false; 49     public static boolean click_flag = false; 50     public static boolean firstload_flag = false;//判断桌面是否是第一次加载 51     public static List<Integer> click_position = new ArrayList<Integer>(); 52     private Intent serviceIntent; 53  54     public static List<ResolveInfo> appInfos; 55     public static List<ResolveInfo> showappInfos; 56     public static  List<Map<String, Object>>  lv_applist = new ArrayList<Map<String,Object>>(); 57     public static  List<Map<String, Object>>  lv_addapplist = new ArrayList<Map<String,Object>>(); 58     public static  List<Map<String, Object>>  lv_delapplist = new ArrayList<Map<String,Object>>(); 59      60     static int []clickinfo; 61  62     static GridView gv_app; 63      64     String []appname ={"联系人","相机","电话","收音机","手电筒","更多"}; 65     int []appicon = {R.drawable.contact,R.drawable.camera,R.drawable.dial,R.drawable.fm,R.drawable.light_off,R.drawable.shop}; 66      67     private Handler mHandler = new Handler() { 68  69         @Override 70         public void handleMessage(Message msg) { 71             super.handleMessage(msg); 72              73              showappInfos = appInfos; 74                  75               76              for(int i=0; i<appInfos.size();i++) { 77                  if((appInfos.get(i).loadLabel(getPackageManager()).equals("相机") && 78                      appInfos.get(i).activityInfo.packageName.equals("com.android.camera")) || 79                     (appInfos.get(i).loadLabel(getPackageManager()).equals("收音机") && 80                     appInfos.get(i).activityInfo.packageName.equals("com.miui.fmradio"))  || 81                     (appInfos.get(i).loadLabel(getPackageManager()).equals("老人桌面") && 82                      appInfos.get(i).activityInfo.packageName.equals("com.highxin.launcher01")) ){ 83                      showappInfos.remove(i); 84                  } 85              } 86              clickinfo = new int[showappInfos.size()]; 87              gv_app.setAdapter(new GridViewAdapter(MainActivity.this,gv_applist)); 88         }      89     }; 90  91      92     @Override 93     protected void onCreate(Bundle savedInstanceState) { 94         super.onCreate(savedInstanceState); 95         requestWindowFeature(Window.FEATURE_NO_TITLE); 96         setContentView(R.layout.activity_main); 97         Drawable drawable_appicon = null; 98         String s_appname = null; 99         serviceIntent = new Intent(this, LightService.class);100 //        if(!firstload_flag) {101             for(int i=0; i<appname.length;i++) {102                 drawable_appicon = getResources().getDrawable(appicon[i]);103                 s_appname = appname[i];104                 Map<String, Object> map = new HashMap<String, Object>();105                 map.put("appname", s_appname);106                 map.put("drawable", drawable_appicon);107                 108                 gv_applist.add(map); 109              }110 //            firstload_flag = true;111 //        }   112         gv_app = (GridView) findViewById(R.id.gv_apps);113         114         gv_app.setOnItemClickListener(this);115 116         Thread t = new Thread(this);117         t.start();118     }119     120     121      private List<Map<String, Object>> fillMaps() {122          List<Map<String, Object>> items = new ArrayList<Map<String, Object>>();123          124          ContentResolver cr = getContentResolver();125          HashMap<String,ArrayList<String>> hashMap = new HashMap<String,ArrayList<String>>();126          Cursor phone = cr.query(CommonDataKinds.Phone.CONTENT_URI, 127            new String[] {128            CommonDataKinds.Phone.CONTACT_ID,129            CommonDataKinds.Phone.DISPLAY_NAME,      130            CommonDataKinds.Phone.NUMBER, 131            CommonDataKinds.Phone.DATA1132            //CommonDataKinds.StructuredPostal.DATA3,133            }, 134            null, null, null);135          while (phone.moveToNext()) {136           String contactId = phone.getString(phone.getColumnIndex(CommonDataKinds.Phone.CONTACT_ID));         137           String displayName = phone.getString(phone.getColumnIndex(CommonDataKinds.Phone.DISPLAY_NAME));138           String PhoneNumber = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));      139           String address = phone.getString(phone.getColumnIndex(CommonDataKinds.Phone.DATA1)); 140           141           //以contactId为主键,把同一人的所有电话都存到一起。142          ArrayList<String> ad = hashMap.get(contactId);143           if(ad == null){144            ad = new ArrayList<String>();145            ad.add(displayName);146            ad.add(PhoneNumber);147            //ad.add(address);148            149            hashMap.put(contactId, ad);150           }151           else{152            ad.add(PhoneNumber);153           }154           155          }156          phone.close();  157          158          ArrayList<String> tmpList;159          String tmpStr = "";160          int k;        161          Iterator iter = hashMap.entrySet().iterator();162          while (iter.hasNext()) {163           HashMap.Entry entry = (HashMap.Entry) iter.next();164              Object key = entry.getKey();165              Object val = entry.getValue();166              167              tmpList = (ArrayList) val;168              tmpStr =  tmpList.get(1);169              //注释掉的为读取多个联系人的方法170 //             for(k = 1; k < tmpList.size(); k++){171 //              tmpStr = tmpStr + tmpList.get(k) + ‘,‘ ;172 //             }173              174              HashMap<String, Object> tmpMap = new HashMap<String, Object>();        175              tmpMap.put("name", tmpList.get(0));176              tmpMap.put("phoneNO", tmpStr);177              tmpMap.put("img", R.drawable.image);178              179              items.add(tmpMap);            180          }                   181          return items;        182      }183 184 185     class GridViewAdapter extends BaseAdapter{186 187         LayoutInflater inflater;188         List<Map<String, Object>> gvlist;189         public GridViewAdapter(Context context,List<Map<String, Object>> locallist) {190             inflater = LayoutInflater.from(context);191             gvlist = locallist;192         }193         @Override194         public int getCount() {195             // TODO Auto-generated method stub196             return gvlist.size();197         }198 199         @Override200         public Object getItem(int position) {201             // TODO Auto-generated method stub202             return gvlist.get(position);203         }204 205         @Override206         public long getItemId(int position) {207             // TODO Auto-generated method stub208             return position;209         }210 211         @Override212         public View getView(int position, View convertView, ViewGroup parent) {213             // TODO Auto-generated method stub214         215                 View view = inflater.inflate(R.layout.gv_item, null);216                 TextView name = (TextView)view.findViewById(R.id.gv_item_appname);217                 ImageView iv = (ImageView)view.findViewById(R.id.gv_item_icon);218                 name.setText((CharSequence) gvlist.get(position).get("appname"));219                 iv.setImageDrawable((Drawable) gvlist.get(position).get("drawable"));220                 221             return view;222         }223         224     }225     226 227     @Override228     protected void onResume() {229         super.onResume();230          gv_app.setAdapter(new GridViewAdapter(MainActivity.this,gv_applist));231     }232 233     @Override234     public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {235         // TODO Auto-generated method stub236         switch(arg2) {237         238             case 0:{239                     contacts_list = fillMaps();240                     Intent contact  = new Intent(MainActivity.this, Contacts.class);241                     startActivity(contact);242                     }break;243             case 1:{244                Intent imageCaptureIntent = new Intent("android.media.action.STILL_IMAGE_CAMERA"); 245                startActivityForResult(imageCaptureIntent,1);246             }break;247             case 2:{248                 Intent i = new Intent();249                 String packageName = "com.android.contacts";250                 String mainActivityName = "com.android.contacts.activities.TwelveKeyDialer";251                 i.setComponent(new ComponentName(packageName,mainActivityName));252                 startActivity(i);253             }break;254             case 3:{255                 Intent intent = new Intent();256                 intent.setPackage("com.miui.fmradio");        257                 startActivityForResult(intent, 3);258                 }break;259             case 4:{260                     switch_flag = !switch_flag;261                     if(switch_flag) {262                         startService(serviceIntent);263                          ImageView iv = (ImageView) arg1.findViewById(R.id.gv_item_icon);264                          iv.setImageResource(R.drawable.light);265                         266                     }else {267                         stopService(serviceIntent);268                          ImageView iv = (ImageView) arg1.findViewById(R.id.gv_item_icon);269                          iv.setImageResource(R.drawable.light_off);270                     }271                 }break;272             case 5:{273                 Intent applist  = new Intent(MainActivity.this, AppList.class);274                 startActivityForResult(applist,5);275                 }break;276             default:{277                 Intent i = new Intent();278                 String packageName = (String) MainActivity.gv_applist.get(arg2).get("pkgname");279                 String mainActivityName = (String) MainActivity.gv_applist.get(arg2).get("activityname");280                 i.setComponent(new ComponentName(packageName,mainActivityName));281                 startActivity(i);282                 283                 284             }break;285         }286     }287 288     @Override289     public void run() {290 291          appInfos = getResolveInfoLists();292          mHandler.sendEmptyMessage(0);293     }294     295     296     /**297      * @Title: getResolveInfoLists298      * @Description: 它是通过解析< Intent-filter>标签得到有   < action299      *               android:name=”android.intent.action.MAIN”/>   < action300      *               android:name=”android.intent.category.LAUNCHER”/>301      * @param302      * @return List<ResolveInfo>303      * @throws304      */305     private List<ResolveInfo> getResolveInfoLists() {306 307         // TODO Auto-generated method stub308         PackageManager packageManager = this.getPackageManager();309 310         Intent intent = new Intent(Intent.ACTION_MAIN);311         intent.addCategory(Intent.CATEGORY_LAUNCHER);312 313         return packageManager.queryIntentActivities(intent, 0);314     }315 316     @Override317     protected void onDestroy() {318         // TODO Auto-generated method stub319         super.onDestroy();320 //        gv_applist.clear();321     }322 323 //    @Override324 //    public boolean onKeyDown(int keyCode, KeyEvent event) {325 //        if (keyCode == KeyEvent.KEYCODE_BACK){326 //            return true;327 //        }328 //        if(keyCode == KeyEvent.KEYCODE_HOME) {329 //            gv_applist.clear();330 //        }331 //    332 //    return super.onKeyDown(keyCode, event);333 //334 //    }335 }


每次按返回键,重新进入程序gv_applist.add(map),会在原来的基础上不断增加。

找到一篇文章是描述的大概也是这个问题:

突然想到了一个问题,因为我在这两个Activity中使用了不一样的结束方式,一个为System.exit(0);一种为finishi();感觉可能是这两个方式造成的,后来经过测试,确实是这两个方式造成的,如果是使用System.exit(0);的方式的话,等于把这个Acitvity结束了,因此他所操作过的数据都不会再存在了,系统也许认为没有存在的必要了吧,使用finishi();的话,虽然也是退出,但是这个并不是释放资源,只是把当前的Activity推向后台,不再显示,但是他不释放资源,具体资源什么时候释放,由系统决定,当然System.exit(0);这种形式,也并不是真正的退出系统,因为我们还可能有别的Activity在运行,但是他确实把资源释放了!这个是为什么,不太明白!

的确重写onDestroy(),调用finish方法还是有这个问题,但是调用System.exit(0)就不存在这个问题啦。如果仅仅就是解决这个问题,当然可以继续坚持使用static变量,要么在destroy方法中对gv_applist清零,要么设置变量判断是不是第一次启动。

 @Override
 protected void onDestroy() {
  // TODO Auto-generated method stub
  super.onDestroy();
//  System.exit(0);
  finish();
  
//  gv_applist.clear();
 }

技术分享

 

但当把这个程序变成桌面程序时,又有一个问题出现啦

         <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />                 <category android:name="android.intent.category.HOME" />                <category android:name="android.intent.category.DEFAULT" />            </intent-filter>        

 技术分享

MainActivity中还有一个变量:static int []clickinfo;这个变量只在点击应用程序后面的按钮时值才会发生改变,为+号时,点击会将图标添加到主屏幕,添加完成之后立即变成-号

技术分享

gv_applist决定主屏幕上加载哪些图标,但当添加完一个图标之后,立即按home键,(桌面程序被推入后台,但是不释放资源,重启桌面程序)会发现主屏幕仍然存在这个图标,但是原来应用列表里面的-号却变成了加号。

if (MainActivity.clickinfo[position] == 0) {                ibt_operate.setImageDrawable(getResources().getDrawable(                        R.drawable.add));            } else {                ibt_operate.setImageDrawable(getResources().getDrawable(                        R.drawable.del));            }

但应用列表里的图标仅仅依据clickinfo变量加载,所以可以断定clickinfo被初始化成全零啦。

static int []clickinfo;
public static  List<Map<String, Object>>  lv_applist = new ArrayList<Map<String,Object>>();

原来定义时,clickinfo没有使用new方法,这种变量进入后台后值是不能够保存的。

如果使用全局变量:

1、尽量减少对代码的同步计算

例如:

for(int i =0;i<list.size;i++){ }

应替换为:

for(int i = 0, int len= list.size();i<len;i++){   }

2、尽量采用lazy loading的策略,在需要的时候才开始创建

例如:

String str = "aaa";    if(i==1){     list.add(str)    }

应替换为:

 if(i ==1){     String str = "aaa"      list.add(str)    }

Android开发中使用static变量应该注意的问题