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.DATA1 132 //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 @Override 194 public int getCount() { 195 // TODO Auto-generated method stub 196 return gvlist.size(); 197 } 198 199 @Override 200 public Object getItem(int position) { 201 // TODO Auto-generated method stub 202 return gvlist.get(position); 203 } 204 205 @Override 206 public long getItemId(int position) { 207 // TODO Auto-generated method stub 208 return position; 209 } 210 211 @Override 212 public View getView(int position, View convertView, ViewGroup parent) { 213 // TODO Auto-generated method stub 214 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 @Override 228 protected void onResume() { 229 super.onResume(); 230 gv_app.setAdapter(new GridViewAdapter(MainActivity.this,gv_applist)); 231 } 232 233 @Override 234 public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { 235 // TODO Auto-generated method stub 236 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 @Override 289 public void run() { 290 291 appInfos = getResolveInfoLists(); 292 mHandler.sendEmptyMessage(0); 293 } 294 295 296 /** 297 * @Title: getResolveInfoLists 298 * @Description: 它是通过解析< Intent-filter>标签得到有 < action 299 * android:name=”android.intent.action.MAIN”/> < action 300 * android:name=”android.intent.category.LAUNCHER”/> 301 * @param : 302 * @return List<ResolveInfo> 303 * @throws 304 */ 305 private List<ResolveInfo> getResolveInfoLists() { 306 307 // TODO Auto-generated method stub 308 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 @Override 317 protected void onDestroy() { 318 // TODO Auto-generated method stub 319 super.onDestroy(); 320 // gv_applist.clear(); 321 } 322 323 // @Override 324 // 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) } |