常见问题及要注意的知识点

来源:互联网 发布:淘宝天猫内部券公众号 编辑:程序博客网 时间:2024/06/05 08:05

1.无论怎么clean project、clean Module Working Directory、clean server、clean Tomcat Working Directory、重启eclipse等,访问web url时总是404,非常奇怪。

解决:把远程地址当成localhost去测试了,晕!

2.在设计数据表时,注意添加必要的索引,否则查询效率很低。

3.一般对于varchar字段要明确设置默认值为NULL而不是”“,否则在映射json对象时会冗余如{"birthday"="",.....}这样不必要的数据,耗损不必要的流量。

4.对于一个view组件,如果设置了layout_margin属性,则在view.setVisibility(View.GONE)后,有可能那些margin还存在,故在此考虑用padding而不是margin。

5.对于一个文件如city.json,在保存时要注意它的编码格式,不然的话,在请求到此资源时是原编码,会导致中文乱码。

6.单例模式中:

class AbcManager {

private AbcManager sInstance;

private XClient mClient;

public static AbcManager get(){
if(sInstance==null){

sInstance = new AbcManager();

}

return sInstance;

}

private AbcManager() {

mClient = new XClient();

}

public void destroy() {

mClient.destroy();

mClient = null;

}

}

切记:在destroy()中应该置空sInstance,否则如果此Manager由于某种原因未被回收,sInstance!=null但mClient==null,从而出现NullPointerException。

一般习惯性以为destroy()被调用后一切都销毁了,但其实只有XClient被销毁了,下次进来时sInstance==null所以XClient不会被重建。

7.关于UI的一些很奇怪的问题:

getAssets().open("city.json");此句放到主线程中执行,后面的UI渲染正常,但放到非主线程中执行UI渲染不出来?????

在非主线程中View view = SysUtil.inflate(layoutid);TextView tv = view.findViewById(id);tv.setText在某些特殊情况下在主线程赋值无效?????这种情况请注意tv是否已经转化为其他孤立的对象如tv转为marker再map.setMarker后此marker上的文本就无法再改变了;在此需要先设置好文本后setMarker或者之后重新setMarker一下。

8.initData时要注意不要重复添加监听器,注:addListener时一定要检查是否已经添加过此监听,不然在initData时重复addListener,导致不仅浪费资源还会造成逻辑错误,如收到某种消息后作一种操作(如添加成功好友后就发一条消息给好友),多了个监听与最初想的逻辑不符。

9.对于自定义一个监听器,如果是在非主线程中调用,则在setListener中回调的代码也是在非主线程中的。

10.单例模式极易弄错且很难找到错误一个地方:

在单例中sInstance是唯一的,这我们都知道,但如果一个类如ABCActivity中有个mMapMgr = 单例,这时切要注意,单例唯一但mMapMgr不是单例,因为单例中sInstance是域变量唯一,但与ABCActivity中的mMapMgr并不统一,所以如果mMapMgr没有随ABCActivity一起销毁就会被误以为mMapMgr就是单例中的sInstance,注意!!!!!!没事不要随便设定一个mgr=XYZManager.get(),因为容易让人忘记mgr其实并不指向sInstance;

11.在layout的xml布局文件中,<include layout="@layout/xxx"/>其中include的view含有id=@+id/abc,如果整个布局中也有id=abc,在编译时不报错错,但运行后会出现异常,因为两id是一样的导致第二个id被前面的id类型覆盖。

12.关于bitmap对象recycle,但要注意一点,如果bitmap已经被回收了,再setImageBitmap就报错:java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@2880e92,如通过getResources().getDrawable(resId)再转为Bitmap对象,如果此bitmap对象被recycle,则再次获取时会获取到上次的被recycle了的bitmap对象,从而导致出错。如bitmap对象被setImageBitmap,之后再bitmap.recycle,仍会立即报同样的错误。recycle要调,同样也要调好。这里附上一方法,Bitmap copyBmp = bitmap.copy(Bitmap.Config.ARGB_8888, false);

13.关于android:process属性,比如在manifest中声明一个service有此属性,则此service跑在另一进程中,与原进程区分开,它们无法共享域变量,此时单例模式失效!

14.关于onTouch的boolean型返回值,如果一个view setOnTouchListener并setOnClickListener,如果onTouch返回false,这时如果产生了一个有效的点击(一个有效的点击事件:在view上点击最后放开时也在view范围内)则onClick会被执行,反之onClick不会执行。onTouch官方对返回值说明:True if the listener has consumed the event, false otherwise.即如果onTouch返回false则说明对view的操作事件未被消费掉(未结束),事件可继续传递下去,可传给其他监听器。如果onTouch返回true,则说明此事件已被消费,到此为止,不会传递下去了。注:在同一个屏幕内的两onTouch事件是不会相干扰的,即在一个view的touch达到第二个有touch监听的view范围,是肯定不可能回调第二个view的onTouch的,因为touch的产生是由第一个view发起的,在onTouch中直接通过view.getId()就可判断。还有一点:onTouch不管返回什么都不会阻止touch事件的继续执行,只是影响此事件传不传下去而已。

15.对于dialog,在new时不会回调onCreate,只有在show时才会onCreate。

16.关于gone、invisible,gone即消失,在<RelativeLayout>中toLeftOf=@+id/abc,如果id=abc的view为gone状态,则toLeftOf相当于没设定,完全等同于没写。在<LinearLayout>中如果设置layout_weight=1,由于另一view的layout_weight=1但状态为gone,则也相当于没有这另一view。如果view的状态设置为invisible,则view的background也会消失哦。

17.关于UTF-8无BOM格式:


如果是默认的UTF-8格式,则带有BOM。UTF-8编码的文件中,BOM占三个字节。如果用记事本把一个文本文件另存为UTF-8编码方式的话,用UE打开这个文件,切换到十六进制编辑状态就可以看到开头的FFFE了。这是个标识UTF-8编码文件的好办法,软件通过BOM来识别这个文件是否是UTF-8编码,很多软件还要求读入的文件必须带BOM。可是,还是有很多软件不能识别BOM。

如果远程一个json文件,如test.json读取到后出现如下情况:


前面有个红点,导致:JSONException: syntax error, pos 1

通常我们看到控制台或通过调试感觉不到此红点,我将控制台打印的json串(看到的其实就是正常的json串)拷贝到"开发工具箱",发现前面多了个如上图的红点。其实这个就是BOM,将test.json编码格式改为无UTF-8 无 BOM格式即可。

有很多客户端不去识别此BOM,但有的识别,所以存储纯粹的json文件时,要注意编码格式。

18.有些异常捕获不到,就交到Application里UncaughtExceptionHandler处理,由于程序崩溃了,但logcat并未打印异常信息,这时就要从uncaughtException(Thread thread, Throwable ex)中去记录下异常了。

19.Executors.newCachedThreadPool().execute(new Runnable(){...});对于此段代码,如果是放到for(N)循环里面和循环外面性质是不一样的,切勿错混成一样的了!如果runnable放到for(N)里面则是创建N个thread,过多的话可能导致Out of memory;如果for(N)循环在runnable里面,则只有一个thread,一切逻辑都是在这个线程里进行,这样当然有弊病,即速度相比肯定就慢了些;多线程当然比单线程计算单元更多运算更快了,速度大约是:V(多线程)=V(单线程)*N。所以要综合考虑速度与内存溢出的平衡,具体对于方法Executors.newFixedThreadPool(M);就要考虑好M值了,对于复杂逻辑处理当然应该用多线程去处理,但M的值要取合理;如果M==1,则相当于newSingleThreadExecutor了(一根管道,先进先出)。注意:一定要搞清楚这个threadPool是在哪创建的,是一个threadPool多个runnable还是多个threadPool,性质是完全不同的,看清楚了!

20.就想要一个域变量不被回收怎么办?可以用序列化或直接用json格式存到sharePreference就行。当然内存是要持续优化好的,要优化代码,要从本源治起。

21.Activity的生命周期与Thread的一个对立极易产生异常:activity销毁后,thread仍执行,所以如果onCreate中执行MyManager.get().getMyData(),对称地在onDestroy中执行MyManager.get().destroy(),但此时thread仍在执行,而里面有用到MyManager.get()的相关方法,这时异步destroy了,故产生NullPointerException异常!!!

所以,在activity中用thread时一定要注意,避免调用activity的生命周期,或者thread与activity生命周期同步create、resume、pause、stop、destroy,否则极易NullPointerException。

22.多线程与间线程处理的区别:多线程即runnnable在循环语句如for循环里面,即有多个runnable;间线程就是runnable在外面,可能包装有一个for循环,但只有一个runnable故为单线程。即:多线程与间线程区别就是runnable的多与寡。在执行复杂大数据处理时,记得用多线程,提高运算速度,让程序飞起来!不要习惯性地在一个threadPool中执行一个for循环!

23.关于bitmap对象的recycle:

如:

Bitmap myBm = xxxobj;

myBm = getSmallBitmap(myBm );

等同于:

Bitmap myBm = xxxobj;

Bitmap newBm = getSmallBitmap(myBm );

myBm = newBm;

这时切要注意recycle不用了的bitmap对象。

这样写是保险的:

Bitmap myBm = xxx;

Bitmap newBm = getSmallBitmap(myBm );

myBm.recycle();

24.URL转发的问题:

java http请求http://host:port/xxx返回一个串:Hello!
如果是在浏览器上访问,返回:

<html>  <head>    <meta name="generator"    content="HTML Tidy for HTML5 (experimental) for Windows https://github.com/w3c/tidy-html5/tree/c63cc39" />    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />    <title>JSP Page</title>  </head>  <body>    <h1>Hello!</h1>  </body></html>
返回的是串:Hello!,由于是用浏览器访问,为显示(以html格式)加了包装,看源码看到被<body>包装显示。
==============================================================================================
URL转发:host:port转发到mydomain。
java http请求http://mydomain/xxx返回的是
<html>  <head>    <meta name="generator"    content="HTML Tidy for HTML5 (experimental) for Windows https://github.com/w3c/tidy-html5/tree/c63cc39" />    <title>My Title</title>    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />  </head>  <frameset cols="0,*" frameborder="NO" border="0" framespacing="0">    <frame src="about:blank" scrolling="no" />    <frame src="http://host:port/xxx" />  </frameset></html>
可以看到<frame>里面有最原始的请求http://host:port/xxx
URL转发是通过frame加载的!

我们在浏览器上通过直接或URL转发看到的页面内容是一样的。

在开发中访问URL转发的地址一定是返回一个带有<frame>的<html>网页串的。

还是那句话:URL转发是通过frame加载的!

在西部数据中,有设置:


即访问http://mynews.xxx.com/test.html就转发到http://211.149.xxx.xxx:8080/News/test.html。

上图中:

1.不隐藏,即在浏览器输入http://mynews.xxx.com/test.html会自动解析跳转到http://211.149.xxx.xxx:8080/News/test.html,这时浏览器地址栏显示的是原始的带有ip地址和端口号的地址,这样直接让人看到ip+port不美观不专业,地址栏也很长。

2.隐藏,即在浏览器输入http://mynews.xxx.com/test.html访问时地址栏不会变。

3.转发标题,这个转发标题是针对设置为“隐藏”来说的,我们知道URL转发是通过frame加载的!。从上面给出的转发后的网页源码可看到里面有个<title>标签,那里面的值就是这里填写的内容。因为真实网址是嵌在<frame>中的。

由上可知:URL转发,如果不隐藏,则ip+port直接暴露不好,好处是标题栏就是原始<html>中的<title>设定的;如果隐藏,则地址栏更美观,但原始<html>中的<title>无效,只能通过控制台设定此url在浏览器的标题。

=》做接口开发,不能用URL转发的地址;用户浏览页面时,用隐藏模式的URL转发地址,别忘了转发标题。

25.onResume、onPause、onStop、onDestroy注意点:对于Activity A、B,A启动B -> A(onPause、onStop)、B(onResume),B按返回键或手动调用finish() -> B(onPause、onStop、onDestroy)

26.主进程死了,在主进程中的service也会挂掉,这时如果在另一service中启动挂掉的 service也会很快跨掉,因为它依赖主进程,所以要先搞活主进程才是解决之道。

27.在dialog中是先构造方法执行,当show()时,onCreate才执行,要注意顺序。

28.registerReceiver相当于addListener,而不是setListener,即注册多次就会收听到多次广播,不要注册过多了!

29.直接startService后,调用stopService并退出程序时,service的onDestroy并没有回调!这往往是由于退出程序时虽然调用了stopServie但还未来得及执行onDestroy就程序exit了。

30.一定木注意多线程产生的NullPointerException,比如Activity finish掉了,回调onDestroy,释放一个正在线程中使用的对象,这时就极易产生NullPointerException了。

31.对于一个view来说,只有它渲染完成了,才能获取到你想要的它的尺寸等信息,比如textview.setText("abc.....xyz");假如它在屏幕上显示有3行,不管是在xml布局文件中还是代码中setText后随后直接调用getLineCount,返回为0。因为setText后渲染是异步进行的,这个要加监听才能行得通,如addOnLayoutChangeListener,监听渲染事件。

32.SQL语句中,in()里面如果什么参数都没有的话,会报BadSqlGrammarException,语法错误!注意判断in里面是否有至少一个参数。

33.多线程导致的域变量值问题,如下拉加载更多,如域变量x=1,下拉进入线程,完成一个耗时操作后,x=x-1,现在连续进行5次下拉加载操作,则这时5个线程共享一个域变量了,问题就来了:本来想着就是完成耗时操作,然后x自减1,但没完成的时候已被其他线程让它自减1操作了,因为这一个变量,大家是共享的!!!

34.Integer默认值为null而非0,故在作判断时,应该是:if(x!=null&&x==0){...}

35.一定要搞清楚在第三方回调方法中,由于处于一种特殊的线程环境(本人暂不清楚为什么叫“特殊”),可能导致域变量在里面都不起效果,如域变量String name, TextView tv,初始化name、tv之后,如果到“特殊”线程里面调用了name、tv,它们全部无效,和初始时一样,这个有点类似于两个进程变量无法共享的效果,切要注意,出现率低,但如果出现,可用handler.sendMessage(msg.what)的方法解决问题。

0 0
原创粉丝点击