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      * @param302      * @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)
    }
posted @ 2014-12-22 11:41  疾风剑  阅读(2290)  评论(0编辑  收藏  举报