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

时间:2021-11-14 07:28:36
 package com.highxin.launcher01;

 import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import android.app.Activity;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.PhoneLookup;
import android.provider.MediaStore;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView; public class MainActivity extends Activity implements Runnable,OnItemClickListener{
String name = "";
String phoneNO = "";
public static List<Map<String, Object>> contacts_list = new ArrayList<Map<String, Object>>();
public static List<Map<String, Object>> gv_applist = new ArrayList<Map<String,Object>>();
public static boolean switch_flag = false;
public static boolean click_flag = false;
public static boolean firstload_flag = false;//判断桌面是否是第一次加载
public static List<Integer> click_position = new ArrayList<Integer>();
private Intent serviceIntent; public static List<ResolveInfo> appInfos;
public static List<ResolveInfo> showappInfos;
public static List<Map<String, Object>> lv_applist = new ArrayList<Map<String,Object>>();
public static List<Map<String, Object>> lv_addapplist = new ArrayList<Map<String,Object>>();
public static List<Map<String, Object>> lv_delapplist = new ArrayList<Map<String,Object>>(); static int []clickinfo; static GridView gv_app; String []appname ={"联系人","相机","电话","收音机","手电筒","更多"};
int []appicon = {R.drawable.contact,R.drawable.camera,R.drawable.dial,R.drawable.fm,R.drawable.light_off,R.drawable.shop}; private Handler mHandler = new Handler() { @Override
public void handleMessage(Message msg) {
super.handleMessage(msg); showappInfos = appInfos; for(int i=0; i<appInfos.size();i++) {
if((appInfos.get(i).loadLabel(getPackageManager()).equals("相机") &&
appInfos.get(i).activityInfo.packageName.equals("com.android.camera")) ||
(appInfos.get(i).loadLabel(getPackageManager()).equals("收音机") &&
appInfos.get(i).activityInfo.packageName.equals("com.miui.fmradio")) ||
(appInfos.get(i).loadLabel(getPackageManager()).equals("老人桌面") &&
appInfos.get(i).activityInfo.packageName.equals("com.highxin.launcher01")) ){
showappInfos.remove(i);
}
}
clickinfo = new int[showappInfos.size()];
gv_app.setAdapter(new GridViewAdapter(MainActivity.this,gv_applist));
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
Drawable drawable_appicon = null;
String s_appname = null;
serviceIntent = new Intent(this, LightService.class);
// if(!firstload_flag) {
for(int i=0; i<appname.length;i++) {
drawable_appicon = getResources().getDrawable(appicon[i]);
s_appname = appname[i];
Map<String, Object> map = new HashMap<String, Object>();
map.put("appname", s_appname);
map.put("drawable", drawable_appicon); gv_applist.add(map);
}
// firstload_flag = true;
// }
gv_app = (GridView) findViewById(R.id.gv_apps); gv_app.setOnItemClickListener(this); Thread t = new Thread(this);
t.start();
} private List<Map<String, Object>> fillMaps() {
List<Map<String, Object>> items = new ArrayList<Map<String, Object>>(); ContentResolver cr = getContentResolver();
HashMap<String,ArrayList<String>> hashMap = new HashMap<String,ArrayList<String>>();
Cursor phone = cr.query(CommonDataKinds.Phone.CONTENT_URI,
new String[] {
CommonDataKinds.Phone.CONTACT_ID,
CommonDataKinds.Phone.DISPLAY_NAME,
CommonDataKinds.Phone.NUMBER,
CommonDataKinds.Phone.DATA1
//CommonDataKinds.StructuredPostal.DATA3,
},
null, null, null);
while (phone.moveToNext()) {
String contactId = phone.getString(phone.getColumnIndex(CommonDataKinds.Phone.CONTACT_ID));
String displayName = phone.getString(phone.getColumnIndex(CommonDataKinds.Phone.DISPLAY_NAME));
String PhoneNumber = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String address = phone.getString(phone.getColumnIndex(CommonDataKinds.Phone.DATA1)); //以contactId为主键,把同一人的所有电话都存到一起。
ArrayList<String> ad = hashMap.get(contactId);
if(ad == null){
ad = new ArrayList<String>();
ad.add(displayName);
ad.add(PhoneNumber);
//ad.add(address); hashMap.put(contactId, ad);
}
else{
ad.add(PhoneNumber);
} }
phone.close(); ArrayList<String> tmpList;
String tmpStr = "";
int k;
Iterator iter = hashMap.entrySet().iterator();
while (iter.hasNext()) {
HashMap.Entry entry = (HashMap.Entry) iter.next();
Object key = entry.getKey();
Object val = entry.getValue(); tmpList = (ArrayList) val;
tmpStr = tmpList.get(1);
//注释掉的为读取多个联系人的方法
// for(k = 1; k < tmpList.size(); k++){
// tmpStr = tmpStr + tmpList.get(k) + ',' ;
// } HashMap<String, Object> tmpMap = new HashMap<String, Object>();
tmpMap.put("name", tmpList.get(0));
tmpMap.put("phoneNO", tmpStr);
tmpMap.put("img", R.drawable.image); items.add(tmpMap);
}
return items;
} class GridViewAdapter extends BaseAdapter{ LayoutInflater inflater;
List<Map<String, Object>> gvlist;
public GridViewAdapter(Context context,List<Map<String, Object>> locallist) {
inflater = LayoutInflater.from(context);
gvlist = locallist;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return gvlist.size();
} @Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return gvlist.get(position);
} @Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub View view = inflater.inflate(R.layout.gv_item, null);
TextView name = (TextView)view.findViewById(R.id.gv_item_appname);
ImageView iv = (ImageView)view.findViewById(R.id.gv_item_icon);
name.setText((CharSequence) gvlist.get(position).get("appname"));
iv.setImageDrawable((Drawable) gvlist.get(position).get("drawable")); return view;
} } @Override
protected void onResume() {
super.onResume();
gv_app.setAdapter(new GridViewAdapter(MainActivity.this,gv_applist));
} @Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
switch(arg2) { case 0:{
contacts_list = fillMaps();
Intent contact = new Intent(MainActivity.this, Contacts.class);
startActivity(contact);
}break;
case 1:{
Intent imageCaptureIntent = new Intent("android.media.action.STILL_IMAGE_CAMERA");
startActivityForResult(imageCaptureIntent,1);
}break;
case 2:{
Intent i = new Intent();
String packageName = "com.android.contacts";
String mainActivityName = "com.android.contacts.activities.TwelveKeyDialer";
i.setComponent(new ComponentName(packageName,mainActivityName));
startActivity(i);
}break;
case 3:{
Intent intent = new Intent();
intent.setPackage("com.miui.fmradio");
startActivityForResult(intent, 3);
}break;
case 4:{
switch_flag = !switch_flag;
if(switch_flag) {
startService(serviceIntent);
ImageView iv = (ImageView) arg1.findViewById(R.id.gv_item_icon);
iv.setImageResource(R.drawable.light); }else {
stopService(serviceIntent);
ImageView iv = (ImageView) arg1.findViewById(R.id.gv_item_icon);
iv.setImageResource(R.drawable.light_off);
}
}break;
case 5:{
Intent applist = new Intent(MainActivity.this, AppList.class);
startActivityForResult(applist,5);
}break;
default:{
Intent i = new Intent();
String packageName = (String) MainActivity.gv_applist.get(arg2).get("pkgname");
String mainActivityName = (String) MainActivity.gv_applist.get(arg2).get("activityname");
i.setComponent(new ComponentName(packageName,mainActivityName));
startActivity(i); }break;
}
} @Override
public void run() { appInfos = getResolveInfoLists();
mHandler.sendEmptyMessage(0);
} /**
* @Title: getResolveInfoLists
* @Description: 它是通过解析< Intent-filter>标签得到有   < action
* android:name=”android.intent.action.MAIN”/>   < action
* android:name=”android.intent.category.LAUNCHER”/>
* @param :
* @return List<ResolveInfo>
* @throws
*/
private List<ResolveInfo> getResolveInfoLists() { // TODO Auto-generated method stub
PackageManager packageManager = this.getPackageManager(); Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER); return packageManager.queryIntentActivities(intent, 0);
} @Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
// gv_applist.clear();
} // @Override
// public boolean onKeyDown(int keyCode, KeyEvent event) {
// if (keyCode == KeyEvent.KEYCODE_BACK){
// return true;
// }
// if(keyCode == KeyEvent.KEYCODE_HOME) {
// gv_applist.clear();
// }
//
// return super.onKeyDown(keyCode, event);
//
// }
}

每次按返回键,重新进入程序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();
 }

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

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

         <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>

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

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

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

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)
}