旅行箱项目问题解决总结



1、当你想要对ListView中的某一个Item进行点击操作的时候,你必须要对其设置tag(将position设置进去),然后给其设置点击事件,在点击事件的响应方法里面判断tag然后处理,但是应该在哪里设置tag是convertView==null里面吗?当然不是,因为listView的优化使得convertView==null里面的代码只会执行一个屏幕可见的次数(例如ListView的item有100个,而屏幕一次可见10个,那么此处代码只会执行10次),因此必须是在外面设置,有100个item就设置100次

2、当你即想响应listView的item的点击方法,也想要响应item里面的某个button的点击方法,那么最好不要给listView设置itemClickListener,而是给convertview以及其中的button各自设置点击事件监听

 

1、如何去掉editText的黑黑的边框?

EditText组件属性里面设置

style="?android:attr/textViewStyle"

        android:background="@null"

 

2、 要实现ScrollView滚动条的隐藏,有两种方法,

 

一种是在XML的ScrollView布局中加入属性android:scrollbars="none"

另一种则是在代码中获取ScrollView后进行设置:

scroll.setVerticalScrollBarEnabled(false);


3、我们的adapter是数据bean和视图View之间的桥梁,因此每次我们在试图上进行了一点修改,我们都应该立即去修改对应的数据bean,但是我们尽量不要已修改数据bean就调用 notifyDataSetChanged();这样可能会导致页面卡顿,所以只需要使用adapter来保持View和Bean的一致性就可以了

2016.10

今天出现一个问题是:

不知怎么的项目编译无法通过,报错说你的一个自定义组件的某个自定义属性已经存在(名字有冲突)?

没有办法一步一步来解决:

只好将这个自定义组件的那个报错的自定义属性修改成其他的名字,好了这个错误不报了,但是接下来又有其他的错误出现,编译的时候报错说:你的一个

包已经存在,于是去看那个包重复,没有发现:于是去SourceTree里面看APP项目下的build.gradle和远端有什么不同,发现多了一个包,去掉之后项目运行正常。之后又将自定义组件的自定义属性修改了过来

关键点是:这里的自定义属性存在的错误其实是因为包的重复导入导致的,但是这个根本问题隐藏在表面问题下,只有根据报错一步一步来,解决了表面问题之后才能让根本问题显示出来


2016.10

今天有了一点关于新建路线页面的想法,因为我发现这个页面没有取消添加的城市的方法,因此我准备修改一下逻辑,将城市选择页面的点击就添加的设计改成点击已经添加过的就删除此城市,因此我们需要去旅行箱里面找一下管理这一块逻辑的方法,我们发现SetTravelActivity是设置形成页面,而这个页面里面的ListView的item是由TravelListAdapter转换的,BusinessUtil和CacheUtil是管理城市list数据的类,而CityChoiceActivity就是添加城市页面,其cityChoice方法就是向CacheUtil里面的HashMap里面的已选城市键值对中的值ArrayList<City>里面添加数据,我们需要修改的就是这个方法的逻辑,这里面selected是已选中的城市集合,position是城市的位置索引

 

但是在看方法的过程中我发现了一个关于JAVA里面的,基本数据类型和引用数据类型的用法:我发现CacheUtil里面的已选城市列表的List,是在上面说的方法里面创建的,而且CacheUtil里面也没有对应的来保存,换句话说CacheUtil保存的就是在CityChoiceActivity的一个方法里面创建的一个引用数据类型对象,也就是说在JAVA里面只要你是引用数据类型,那么你传递的时候,就是直接传递的地址,所有的修改也都是直接针对你最初创建爱你的那个对象进行的

 

 2016.11

今天遇到的一个问题是:旅行箱应用用AndroidStudio竟然无法运行!报错是:Unsupported method: AndroidProject.getPluginGeneration()

上网查了一下说是AndroidStudio升级了之后,每次运行会检查快速运行Instant Run这个特性,而可能你的应用的gradle版本不支持这个特性,因此需要在setting里面关掉Instant Run



今天的问题是:当你使用for循环向arraylist中添加对象的时候,你要知道JAVA中对象是直接传递地址的因此如果你仅仅只是new了一次对象,然后在循环里面对其重新赋值,然后添加其实是不行的,因此你最终的结果是仅仅添加了一次对象

 

 

什么叫做内存泄漏?

其实内存泄漏不是一种现象,比如OOM这些我们能够看到的异常情况,更多的时候是一个说法,一种有关于内存优化的一种说法,如果一个系统的内存无限大那也就不存在内存泄漏的问题了

内存泄漏指的是:Java内存泄漏指的是进程中某些对象(垃圾对象)已经没有使用价值了,但是它们却可以直接或间接地引用到gc  roots导致无法被GC回收。无用的对象占据着内存空间,使得实际可使用内存变小,形象地说法就是内存泄漏了

常见内存泄漏场景:

http://blog.csdn.net/cyq1028/article/details/19980369

1、例如PopupWindowUtil类,此类里面的PopupWindow变量是静态的,因此如果你第一次进行PopupWindowUtil的初始化操作,而这个类是单例且静态的,因此PopupWindow就不会被释放,而此时我们并不需要这个PopupWindow一直存在,因此就出现了内存泄漏,我们的解决办法就是,在逻辑中每次让PopupWindow消失的时候就讲其置为null。

2、Activity的引用的生命周期超越了activity对象的生命周期。也就是常说的Context泄漏,因为activity就是context

想要避免context相关的内存泄漏,需要注意以下几点:

·不要对activity的context长期引用(一个activity的引用的生存周期应该和activity的生命周期相同)

·如果可以的话,尽量使用关于application的context来替代和activity相关的context

·如果一个acitivity的非静态内部类的生命周期不受控制,那么避免使用它;正确的方法是使用一个静态的内部类,并且对它的外部类有一WeakReference

3、我们知道,Handler通过发送Message与主线程交互,Message发出之后是存储在MessageQueue中的,有些Message也不是马上就被处理的。在Message中存在一个 target,是Handler的一个引用,如果Message在Queue中存在的时间越长,就会导致Handler无法被回收。如果Handler是非静态的,则会导致Activity或者Service不会被回收(因为Handler一般是定义成内部类)。 所以正确处理Handler等之类的内部类,应该将自己的Handler定义为静态内部类。然后使用弱引用。

 

 

什么叫隐式引用?

例如:Java的非静态内部类会隐式的拥有一个外部类的引用,为什么这么说,因为JAVA中调用方法是需要对象的,而非静态内部类可以调用外部类的方法,也就是说这个内部类对象持有其外部类的引用,否则怎么调用其方法,同理所谓隐式引用就是虽然没有类似于Person p = new Person();这样变量p显式的引用到Person对象。但是任然可以调用到Person对象的方法。

 

Android多线程

每开一个线程就会至少耗费64K+的内存,

 

Android的Handler机制

http://blog.csdn.net/lmj623565791/article/details/38377229

Handler在哪里创建就会和哪个线程绑定在一起,创建一个消息最好用message.obtain(),因为message内部维护了一个消息池

1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。

2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。

3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。

4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。

5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。

好了,总结完成,大家可能还会问,那么在Activity中,我们并没有显示的调用Looper.prepare()和Looper.loop()方法,为啥Handler可以成功创建呢,这是因为在Activity的启动代码中,已经在当前UI线程调用了Looper.prepare()和Looper.loop()方法。

 

另一种:mHandler.post(new Runnable() {});

其实这种方式并没有创建出一个新的Thread,不要仅仅看到Runnable就以为创建了一个新的线程,其实新线程的创建是Thread的start()方法引发的,在start()方法里面有一个native方法nativeCreate()此方法才是创建线程的方法。也就是说你需要将代码逻辑和真实运行分开

 

2016.11

今天在解决魅族手机上显示高德导航页面时,直接卡死的问题:

1、按照官方文档更换了so库,从2.x版本升级到了3.x版本,

具体步骤见:http://lbs.amap.com/dev/ticket#/faq/349/

2、然后又出现了新的问题:魅族手机上可以正常显示了,但是其他手机上又出问题了,显示的是白屏,例如:华为和小米

3、然后再次排错发现华为手机上不能正常使用时由于手机上装的高德导航的版本有问题导致的,但是小米手机上始终不行

4、最后在向高德导航平台进行咨询之后,找到了问题的根源:

需要在APP的gradle里面配置这么一段代码:

splits {

        abi {

            enable true

            reset()

            include 'armeabi'//只打包armeabi平台的,就算有其他文件夹也不管

//          include 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'x86', 'x86_64'

        }

}

解决问题,但是又有新的问题:那就是只打包abi框架下的so库,会不会影响应用在部分手机上的性能?

 

当然会影响,所以这样是不行的,最后原来还是需要按照统一的3D地图的配置进行配置:也就是:安装所需的三个jar包,安装armeabi架构和arme64-v8a架构下的so文件。

但是之前也是按照这样的架构设计的为什么不行呢?

原来之前是傻得竟然直接把armeabi下的so文件复制到了arme64-v8a里面了,而这样当然是不行的,你要知道这些so库是用来适配对应CPU架构的,当然不同的架构需要不同的so库了,你直接复制当然是不行的

 

2016.11

今天发现一个问题:就是当我在AndroidStudio中新建一个工程的时候,发现我自定义的application的onCreate()方法,一直没有被调用

最后查找资料才发现原来需要在manifest.xml文件里面,将application标签的name属性的值定义成你自定义的application,就像你继承activity得来的自定义activity一样。

 

2016.12

怎样快速新建一个工程?

不要舍本逐末,要将一些不必要的东西去掉,直接使用最核心的功能,例如一些基础的封装工具类等,这些是暂时不需要的,最短的时间内实现功能才是你需要考虑的,就比如今天测试地图功能,那么你只需要一个页面,提供一个入口,然后一个页面展示地图就可以了,其他的一切从简,最简单的,你可能只需要一个application和一个activity,就可以了

 

2016.12

Android项目apk体积优化:

AndroidStudio的APP项目下的build目录是每次编译程序时自动生成的,因此我们可以直接删除,另外这个目录下的outputs目录下的apk文件夹下的apk可以直接点开,然后可以仔细的看应用的内存占用主要是消耗在哪里了

 

2016.12

今天遇到一个问题:就是需要在Androidstudio里面添加一个引用例如:

compile'org.greenrobot:greendao:3.2.0',我们知道你的项目要想引用到其他的库,就必须调用人家的代码,那么久必须下载人家的代码,所以从根本上引用库就两种,一种是直接下载代码的jar包等,然后引用,一种是在Android的库中心利用网络下载,然后安装

2017.3.2

今天遇到一个AndroidStudio的问题:

当我们打开AndroidStudio的时候,发现所有的JAVA类都不能正常的显示成C,而是显示成J,而且xml文件编辑属性的时候不会自动提示,关闭AndroidStudio再次打开,发现提示Power Saving Mode(省电模式),关闭之后一切正常




1、当你想要对ListView中的某一个Item进行点击操作的时候,你必须要对其设置tag(将position设置进去),然后给其设置点击事件,在点击事件的响应方法里面判断tag然后处理,但是应该在哪里设置tag是convertView==null里面吗?当然不是,因为listView的优化使得convertView==null里面的代码只会执行一个屏幕可见的次数(例如ListView的item有100个,而屏幕一次可见10个,那么此处代码只会执行10次),因此必须是在外面设置,有100个item就设置100次

2、当你即想响应listView的item的点击方法,也想要响应item里面的某个button的点击方法,那么最好不要给listView设置itemClickListener,而是给convertview以及其中的button各自设置点击事件监听

 


 

1、如何去掉editText的黑黑的边框?

EditText组件属性里面设置

style="?android:attr/textViewStyle"

        android:background="@null"

 

2、 要实现ScrollView滚动条的隐藏,有两种方法,

 

一种是在XML的ScrollView布局中加入属性android:scrollbars="none"

另一种则是在代码中获取ScrollView后进行设置:

scroll.setVerticalScrollBarEnabled(false);


3、我们的adapter是数据bean和视图View之间的桥梁,因此每次我们在试图上进行了一点修改,我们都应该立即去修改对应的数据bean,但是我们尽量不要已修改数据bean就调用 notifyDataSetChanged();这样可能会导致页面卡顿,所以只需要使用adapter来保持View和Bean的一致性就可以了

2017.2.9

今天出现一个问题是:

不知怎么的项目编译无法通过,报错说你的一个自定义组件的某个自定义属性已经存在(名字有冲突)?

没有办法一步一步来解决:

只好将这个自定义组件的那个报错的自定义属性修改成其他的名字,好了这个错误不报了,但是接下来又有其他的错误出现,编译的时候报错说:你的一个

包已经存在,于是去看那个包重复,没有发现:于是去SourceTree里面看APP项目下的build.gradle和远端有什么不同,发现多了一个包,去掉之后项目运行正常。之后又将自定义组件的自定义属性修改了过来

关键点是:这里的自定义属性存在的错误其实是因为包的重复导入导致的,但是这个根本问题隐藏在表面问题下,只有根据报错一步一步来,解决了表面问题之后才能让根本问题显示出来



今天有了一点关于新建路线页面的想法,因为我发现这个页面没有取消添加的城市的方法,因此我准备修改一下逻辑,将城市选择页面的点击就添加的设计改成点击已经添加过的就删除此城市,因此我们需要去旅行箱里面找一下管理这一块逻辑的方法,我们发现SetTravelActivity是设置形成页面,而这个页面里面的ListView的item是由TravelListAdapter转换的,BusinessUtil和CacheUtil是管理城市list数据的类,而CityChoiceActivity就是添加城市页面,其cityChoice方法就是向CacheUtil里面的HashMap里面的已选城市键值对中的值ArrayList<City>里面添加数据,我们需要修改的就是这个方法的逻辑,这里面selected是已选中的城市集合,position是城市的位置索引

 

但是在看方法的过程中我发现了一个关于JAVA里面的,基本数据类型和引用数据类型的用法:我发现CacheUtil里面的已选城市列表的List,是在上面说的方法里面创建的,而且CacheUtil里面也没有对应的来保存,换句话说CacheUtil保存的就是在CityChoiceActivity的一个方法里面创建的一个引用数据类型对象,也就是说在JAVA里面只要你是引用数据类型,那么你传递的时候,就是直接传递的地址,所有的修改也都是直接针对你最初创建爱你的那个对象进行的

 

 

今天遇到的一个问题是:旅行箱应用用AndroidStudio竟然无法运行!报错是:Unsupported method: AndroidProject.getPluginGeneration()

上网查了一下说是AndroidStudio升级了之后,每次运行会检查快速运行Instant Run这个特性,而可能你的应用的gradle版本不支持这个特性,因此需要在setting里面关掉Instant Run



今天的问题是:当你使用for循环向arraylist中添加对象的时候,你要知道JAVA中对象是直接传递地址的因此如果你仅仅只是new了一次对象,然后在循环里面对其重新赋值,然后添加其实是不行的,因此你最终的结果是仅仅添加了一次对象

 

 

 

RXJava中的转换Flatmap()的原理在于lift()方法里面,而这个方法中的关键点就是:闭包,使得你没看错就是JavaScript里面的闭包,闭包是一种函数,可以理解成是“定义在一个函数内部的函数”有了闭包我们就可以在函数外部读取函数内部的变量,这就是JavaScript里面的闭包

RXJAVA中lift()方法对闭包的利用就是:在 Observable 执行了 lift(Operator) 方法之后,会返回一个新的 Observable,这个新的 Observable 会像一个代理一样,负责接收原始的 Observable 发出的事件,并在处理后发送给 Subscriber(当然因为JAVA的成员变量的作用范围的问题,这里接受原始的Observable发出的事件可定也是在lift()方法内部,也就是在原来的Observable内部,这样才能直接操作Observable的变量)


什么叫做内存泄漏?

其实内存泄漏不是一种现象,比如OOM这些我们能够看到的异常情况,更多的时候是一个说法,一种有关于内存优化的一种说法,如果一个系统的内存无限大那也就不存在内存泄漏的问题了

内存泄漏指的是:Java内存泄漏指的是进程中某些对象(垃圾对象)已经没有使用价值了,但是它们却可以直接或间接地引用到gc  roots导致无法被GC回收。无用的对象占据着内存空间,使得实际可使用内存变小,形象地说法就是内存泄漏了

常见内存泄漏场景:

http://blog.csdn.net/cyq1028/article/details/19980369

1、例如PopupWindowUtil类,此类里面的PopupWindow变量是静态的,因此如果你第一次进行PopupWindowUtil的初始化操作,而这个类是单例且静态的,因此PopupWindow就不会被释放,而此时我们并不需要这个PopupWindow一直存在,因此就出现了内存泄漏,我们的解决办法就是,在逻辑中每次让PopupWindow消失的时候就讲其置为null。

2、Activity的引用的生命周期超越了activity对象的生命周期。也就是常说的Context泄漏,因为activity就是context

想要避免context相关的内存泄漏,需要注意以下几点:

·不要对activity的context长期引用(一个activity的引用的生存周期应该和activity的生命周期相同)

·如果可以的话,尽量使用关于application的context来替代和activity相关的context

·如果一个acitivity的非静态内部类的生命周期不受控制,那么避免使用它;正确的方法是使用一个静态的内部类,并且对它的外部类有一WeakReference

3、我们知道,Handler通过发送Message与主线程交互,Message发出之后是存储在MessageQueue中的,有些Message也不是马上就被处理的。在Message中存在一个 target,是Handler的一个引用,如果Message在Queue中存在的时间越长,就会导致Handler无法被回收。如果Handler是非静态的,则会导致Activity或者Service不会被回收(因为Handler一般是定义成内部类)。 所以正确处理Handler等之类的内部类,应该将自己的Handler定义为静态内部类。然后使用弱引用。

 

 

什么叫隐式引用?

例如:Java的非静态内部类会隐式的拥有一个外部类的引用,为什么这么说,因为JAVA中调用方法是需要对象的,而非静态内部类可以调用外部类的方法,也就是说这个内部类对象持有其外部类的引用,否则怎么调用其方法,同理所谓隐式引用就是虽然没有类似于Person p = new Person();这样变量p显式的引用到Person对象。但是任然可以调用到Person对象的方法。

 

Android多线程

每开一个线程就会至少耗费64K+的内存,

 

Android的Handler机制

http://blog.csdn.net/lmj623565791/article/details/38377229

Handler在哪里创建就会和哪个线程绑定在一起,创建一个消息最好用message.obtain(),因为message内部维护了一个消息池

1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。

2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。

3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。

4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。

5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。

好了,总结完成,大家可能还会问,那么在Activity中,我们并没有显示的调用Looper.prepare()和Looper.loop()方法,为啥Handler可以成功创建呢,这是因为在Activity的启动代码中,已经在当前UI线程调用了Looper.prepare()和Looper.loop()方法。

 

另一种:mHandler.post(new Runnable() {});

其实这种方式并没有创建出一个新的Thread,不要仅仅看到Runnable就以为创建了一个新的线程,其实新线程的创建是Thread的start()方法引发的,在start()方法里面有一个native方法nativeCreate()此方法才是创建线程的方法。也就是说你需要将代码逻辑和真实运行分开

 


今天在解决魅族手机上显示高德导航页面时,直接卡死的问题:

1、按照官方文档更换了so库,从2.x版本升级到了3.x版本,

具体步骤见:http://lbs.amap.com/dev/ticket#/faq/349/

2、然后又出现了新的问题:魅族手机上可以正常显示了,但是其他手机上又出问题了,显示的是白屏,例如:华为和小米

3、然后再次排错发现华为手机上不能正常使用时由于手机上装的高德导航的版本有问题导致的,但是小米手机上始终不行

4、最后在向高德导航平台进行咨询之后,找到了问题的根源:

需要在APP的gradle里面配置这么一段代码:

splits {

        abi {

            enable true

            reset()

            include 'armeabi'//只打包armeabi平台的,就算有其他文件夹也不管

//          include 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'x86', 'x86_64'

        }

}

解决问题,但是又有新的问题:那就是只打包abi框架下的so库,会不会影响应用在部分手机上的性能?

 

当然会影响,所以这样是不行的,最后原来还是需要按照统一的3D地图的配置进行配置:也就是:安装所需的三个jar包,安装armeabi架构和arme64-v8a架构下的so文件。

但是之前也是按照这样的架构设计的为什么不行呢?

原来之前是傻得竟然直接把armeabi下的so文件复制到了arme64-v8a里面了,而这样当然是不行的,你要知道这些so库是用来适配对应CPU架构的,当然不同的架构需要不同的so库了,你直接复制当然是不行的

 


今天发现一个问题:就是当我在AndroidStudio中新建一个工程的时候,发现我自定义的application的onCreate()方法,一直没有被调用

最后查找资料才发现原来需要在manifest.xml文件里面,将application标签的name属性的值定义成你自定义的application,就像你继承activity得来的自定义activity一样。

 

怎样快速新建一个工程?

不要舍本逐末,要将一些不必要的东西去掉,直接使用最核心的功能,例如一些基础的封装工具类等,这些是暂时不需要的,最短的时间内实现功能才是你需要考虑的,就比如今天测试地图功能,那么你只需要一个页面,提供一个入口,然后一个页面展示地图就可以了,其他的一切从简,最简单的,你可能只需要一个application和一个activity,就可以了

 

Android项目apk体积优化:

AndroidStudio的APP项目下的build目录是每次编译程序时自动生成的,因此我们可以直接删除,另外这个目录下的outputs目录下的apk文件夹下的apk可以直接点开,然后可以仔细的看应用的内存占用主要是消耗在哪里了

 


今天遇到一个问题:就是需要在Androidstudio里面添加一个引用例如:

compile'org.greenrobot:greendao:3.2.0',我们知道你的项目要想引用到其他的库,就必须调用人家的代码,那么久必须下载人家的代码,所以从根本上引用库就两种,一种是直接下载代码的jar包等,然后引用,一种是在Android的库中心利用网络下载,然后安装

2017.3.2

今天遇到一个AndroidStudio的问题:

当我们打开AndroidStudio的时候,发现所有的JAVA类都不能正常的显示成C,而是显示成J,而且xml文件编辑属性的时候不会自动提示,关闭AndroidStudio再次打开,发现提示Power Saving Mode(省电模式),关闭之后一切正常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值