Android项目总结-新手常见误区-JAVA。

1、null问题

当对象(基本数据类型、定义的Class对象)只声明未实例化时,其为null.
如:

Date  a;	//此时给a在栈中分配一个空间保存a变量,a为null。
a=new Date();	//此时在堆中开辟Date对象的数据空间,并把该空间的首地址赋值给a。
Date  b=a;	//b引用a,将a保存的地址赋给b。在单线程中,a,b的改变同步。即此时改变b中的数据,a中数据同步改变。

在调试中,经常抛出null引用问题。
其原因是:当对象为null时,无法执行任何方法,常见的是执行String.clear()、String.add()等。
解决方法:当有null数据需要进行操作时,先进行if语句的判断。

2、Fragment增删动态更新问题。

当用ViewPage+(FragmentList-FragmentAdapter)时,存在Fragment动态更新问题。造成原因是FragmentPagerAdapter的源码当中的instantiateItem()方法,其根据tag查找对应的Fragment, 如果找到,那么就通过当前的Transaction进行attach操作,这个fragment就会显示了,如果没有找到,就用getItem()从你的Fragment列表中获取一个然后Transaction进行add操作。(自己看一下FragmentAdapter的源码就知道怎么回事了,很清晰简单),如果比较懒的话可参考分析:https://blog.csdn.net/lyabc123456/article/details/79797552
网上教程是通过Transaction删除fragment,但该方法存在问题或没有解释完整。通过调试发现其删除fragment的逻辑如下图所示,其删除了fragment,但该位置仍然存在,Fragment重排序后存在一个空fragment。
在这里插入图片描述
如此导致当再增加一个Fragment后,第三个位置将直接attach一个空Fragment。新增的Fragment无效。
解决方法:对于删除Fragment后有再增加Fragment的需求,再删除操作中应直接通过Transaction删除所有内存中的Fragment,重新实例化FragmentAdapter对象刷新内存,可避免空Fragment的存在。
对于Fragment内容更新,则直接获取FragmentList中的Fragment,利用Handle将其在主线程中修改内容即可更新UI。

3、==判断

在对String进行相等条件判断是,误用“==”进行相等判断出现bug。
问题原因“==”比教的是两个非null对象的地址。使用==判断的情况一般用于基本数据类型及对象为null。对两个String对象进行判断时应使用String.equals()方法。equals()方法比较的是两个对象的内容值。
导致后果:不会出现程序异常,当会导致逻辑错误。
[color=#FF0000]解决方法[/color]:使用equals()方法比较是否相等。

4、非UI线程更改UI组件

UI界面的创建与修改都是在UI线程中,界面创建后,各种事件(如点击事件)的处理方法是在UI线程中的,故此时可修改UI组件。但当需要在其他线程中修改UI组件的情境中,如新建网络请求线程,获取数据后更新UI组件显示,此时对UI组件的修改需要通过handle运行在主线程中。
在weather模块中遇到两处网络请求线程中更新UI组件操作,第一是请求城市,用返回的城市列表数据更新RecycleAdapter,第二处是请求天气,用返回的天气数据更新Fragment。由于部分更新操作未放到UI线程中出错。
解决方法:在主线程中创建Handle,用handle.post() 或handle.handleMessage()将在其他线程中更新UI组件的操作放到UI线程中,handle的两种使用方法见:https://blog.csdn.net/mountain_hua/article/details/81291677
关于对UI组件的更改包括常见的(1)UI组件内容修改;(2)UI组件的增删及visible属性设置;(3)notifydatasetchanged(); 对于像Adapter中list的修改(weather中的recycleAdatper),之后调用notifydatasetchanged();都应放到主线程中,否则会出错,实际过程中遇到了网络请求线程结束后UI界面有时改变有时不改变,好像是线程的时序问题。
总之所有在非UI线程中涉及的对UI界面的任何修改都应放到主线程中

5、多线程共享数据的同步

<本段仅作为个人项目问题小节,估计只有自己能看懂写的啥>
<总之有数据共享时,多线程条件下务必保持数据“可见性”,这是由于java内存机制的原理导致的,具体说明可直接看给出的参考链接>

在weather模块中,为了获得界面显示的所有天气信息,需要请求多个url,多次更新特定位置上一个Fragment上不同位置的内容,且网络请求的响应速度不同,对界面的更新顺序无法保证,为保证代码的共用性,对Fragment上的不同位置的更新使用同一个更新方法,且使用相同的共享数据类型。如此便在多个线程中使用同一个对象WeatherBean,因此必须保证共享数据的可见性。否则会产生错误。
问题原因:程序中的数据存储在主内存中,每个线程有自己的工作内存,当线程需要使用共享数据时,会将主内存中的数据拷贝至自己的工作内存中,之后的操作会使用拷贝的数据,而不会使用主内存中的数据。如:
共享数据WeatherBean为:share={tmp=null,air=null};
线程1与线程2同时获取share, 两个线程分别读取share,并且把share存到了各自的工作内存中,然后线程1获取了tmp数据为10,赋值给share的tmp,此时线程1中share={tmp=10,air=null},并且把tmp的值写回到主存中。但是线程2中工作内存的share={tmp=null,air=null},当线程2获取了air数据为“晴”,其share={tmp=null,air=“晴”},线程1获取数据后进行Fragment.update(share),此时fragment中tmp显示10,air显示空,线程2获取数据后进行Fragment.update(share),此时fragment中tmp显示空,air显示“晴”,所以导致fragment无法正确更新。
解决方法:使用volatile修饰需要共享的数据,保证数据的“可见性”,关于volatile的用法可见:
https://www.cnblogs.com/kubidemanong/p/9505944.html
https://blog.csdn.net/mccand1234/article/details/91345168.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值