Android开发中使用static变量应该注意的问题
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();
}
但当把这个程序变成桌面程序时,又有一个问题出现啦
<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){ |
Android开发中使用static变量应该注意的问题的更多相关文章
- Android开发中常见的设计模式
对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次.而在android开发中,必要的了解一些设计模式又是非常有必要的.对于想系统的学习设计模式的 ...
- android开发中的5种存储数据方式
数据存储在开发中是使用最频繁的,根据不同的情况选择不同的存储数据方式对于提高开发效率很有帮助.下面笔者在主要介绍Android平台中实现数据存储的5种方式. 1.使用SharedPreferences ...
- Android开发中使用七牛云存储进行图片上传下载
Android开发中的图片存储本来就是比较耗时耗地的事情,而使用第三方的七牛云,便可以很好的解决这些后顾之忧,最近我也是在学习七牛的SDK,将使用过程在这记录下来,方便以后使用. 先说一下七牛云的存储 ...
- 讨论Android开发中的MVC设计思想
最近闲着没事,总是想想做点什么.在时间空余之时给大家说说MVC设计思想在Android开发中的运用吧! MVC设计思想在Android开发中一直都是一套比较好的设计思想.很多APP的设计都是使用这套方 ...
- Android开发中的输入合法性检验
Why ? 合法性检查对于程序的健壮性具有重要作用.在Android开发中,良好的合法性检查设计机制可以使程序更加清晰,产生bug更少,交互更加友好. What ? 合法性检查的目的在于确定边界.对于 ...
- 关于Android开发中的证书和密钥等问题
关于Android开发中的证书和密钥等问题 引言 除了Android发布应用签名时需要用到证书外,在进行google Map Api开发和Facebook SDK API开发等时都需要申请API Ke ...
- Android开发中,那些让您觉得相见恨晚的方法、类或接口
Android开发中,那些让你觉得相见恨晚的方法.类或接口本篇文章内容提取自知乎Android开发中,有哪些让你觉得相见恨晚的方法.类或接口?,其实有一部是JAVA的,但是在android开发中也算常 ...
- android开发中系统自带语音模块的使用
android开发中系统自带语音模块的使用需求:项目中需要添加语音搜索模块,增加用户体验解决过程:在网上搜到语音搜索例子,参考网上代码,加入到了自己的项目,完成产品要求.这个问题很好解决,网上能找到很 ...
- 如何在Android开发中让你的代码更有效率
最近看了Google IO 2012年的一个视频,名字叫做Doing More With Less: Being a Good Android Citizen,主要是讲如何用少少的几句代码来改善And ...
随机推荐
- Andorid自动读取短信验证码
手机收到验证码短信后,程序自动识别验证码并填充验证码输入框. 思路是有了,实现的方式也有多种: 1.开启一个线程,隔一段时间就去查询收件箱是否有变化,有变化再读取出来做处理. 2.注册一个短信变化的广 ...
- DataTable源码分析(二)
DataTable源码分析(二) ===================== DataTable函数分析 ---------------- DataTable作为整个插件的入口,完成了整个表格的数据初 ...
- !function 笔记
一般看JQuery插件里的写法是这样的 (function($) { //... })(jQuery); 今天看到bootstrap的javascript组件是这样写的 !function( $ ){ ...
- C# 超高速高性能写日志 代码开源
1.需求 需求很简单,就是在C#开发中高速写日志.比如在高并发,高流量的地方需要写日志.我们知道程序在操作磁盘时是比较耗时的,所以我们把日志写到磁盘上会有一定的时间耗在上面,这些并不是我们想看到的. ...
- 给指针malloc分配空间后就等于数组吗?【转】
首先回答你的问题:严格的说不等于数组,但是可以认为它是个数组一样的使用而不产生任何问题. 不过既然这样,那它应该算是个数组吧.所以,一般我们都用“动态数组”这种名字来称呼这种东西. 要讲清楚这个东西, ...
- 转账示例(四):service层面实现(线程管理Connection,AOP思想,动态代理)(本例采用QueryRunner来执行sql语句,数据源为C3P0)
用了AOP(面向切面编程),实现动态代理,service层面隐藏了开启事务.1.自行创建C3P0Uti,account数据库,导入Jar包 2.Dao层面 接口: package com.learni ...
- 排序算法合集 python
直接选择.插入排序 直接选择排序和直接插入排序类似,都将数据分为有序区和无序区,所不同的是直接播放排序是将无序区的第一个元素直接插入到有序区以形成一个更大的有序区,而直接选择排序是从无序区选一个最小的 ...
- json数据渲染表单元素出现的问题
解析页面表单元素 parseForm: function () { var data = {}; $(this).find('input').each(function () { switch ($( ...
- 【Vue 入门】使用 Vue2 开发一个展示项目列表的应用
前言 一直没有找到一个合适的展示个人项目的模板,所以自己动手使用 Vue 写了一个.该模板基于 Markdown 文件进行配置,只需要按一定规则编写 Markdown 文件,然后使用一个 在线工具 转 ...
- Mongo汇总问题
1. 数据 /* 5 */ { "_id" : ObjectId("5902f7ca2b3fe442d60a0946"), "code" : ...