前阶段的Android学习总结
前阶段的Android学习总结
半年一更新,一更拖半年……前阶段直至在“不踏实”地学习Android知识;跟了不少视频,看了不少书;实际上学地都不踏实;直到今天彻底迷茫,不知道该怎样“系统地”学习Android;我想那不如把前阶段的收获总结分享一下吧:
如果你从中有所收获的话,请给我点个赞鼓励下吧!????
一、Android Studio导入现有工程的几个步骤
这里是参考的:“Android Studio导入现有工程的几个步骤.”
概括以下四步:
- 根目录下的 build.gradle里定义了gradle tool的版本号;手动修改这里的版本号为当前支持的版本号:
- 根目录下的gradle\wrapper里的gradle-wrapper.properties文件修改为自己的gradle配置中的zip包的版本;
- 最后修改一下app模块下的build.gradle;对应的sdk的版本,build tool的版本号,以及一些依赖的jar包;
- 如果Android studio运行出错 compilation failed see the compiler error output for details.;点击下图圈圈;切换一下显示模式;就可以具体修改代码中的错误;
二、这里推荐一篇好文
这篇文章里有不少经验分享和资料分享: Android小白学习成长路线.
三、四大应用组件之ContentProvider
不知道这里为什么会有这篇经验;如有侵权,请联系我立即删除!
-
理解
1). 为会么要有ContentProvider?
2). ContentProvider是什么? -
相关API:
1). ContentProvider: 内容提供者类
2). ContentResolver: 内容解析器类 :
3). Uri: 包含一个具有一定格式的字符串所对应资源的类
4). UriMatcher: 用来识别uri的一个uri容器
5). ContentUris: 操作uri的工具类 -
自定义ContentProvider
-
使用ContentResolver访问ContentProvider
-
应用练习
1). 使用 ConentResolver 查询得到所有联系人数据列表
2). 使用 ListView + BaseAdapter 显示列表
3). 使用带回调启动 Activity 和带结果的返回
四、Git
- 期间里用一周时间了解了一下Git;
- 学习资料当然是“业界公认"的: 廖雪峰的官方网站.
我打起了广告?额……不管了,自己的学习总结而已;
五、View学习总结和BUG
-
ListView
- 设置一个ListView并找到;
- 初始化数据(把数据装到集合里);
- 数据设置到adapter中;
- adapter 又设置给ListView;
- 难点在于自定义adapter;
a. 自定义adapter继承与ArrayAdapter<或BaseAdapter>;并产生其构造器;
b. 重写 .getView() ;此时 ListView 中每一个项目可用 .getItem() 获得;
c. 其中重写了一个 ViewHolder 类;
d. 难点 在于两步优化和 .getView() 的理解。 -
BUG:判断 ArrayList 中是否为空;绝不能用
mFruitList == null;
要用 mFruitList.size() == 0 代替
疑问:"com/example/listviewtest/FruitActivity.java:25"中;去重方法 写了;可是,每次打开软件都是重新填充数据,而不会用到去重方法。.
-
BUG :List 使用 add 方法时;List集合add方法覆盖原来的内容 ;修改 用 addAll 复制得到的数据 arrayList 中 ,修改数据时,原数据也被修改;结果就是,最终添加的结果都一样,全都是最后一次add的效果,<都是Java基础不扎实的原因啊>
a. 这是因为,arrayList 的性质!如果元素是引用类型,保存的是引用,如果是值类型,保存的是值本身。这里addAll 只是复制了地址,并非复制了全部的元素!同理,数据的add(),可以在set()前,也可在其后;
b.解决方法:就是每次循环的时候,都把要添加的对象, new 一遍然后进行 set 等操作;如果元素是 值类型 ,那么就不许重复 new 对象;
c. 那么如何复制 集合中的元素!还是老老实实的遍历吧…… -
BUG
Android报错:Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
解决方法:
1. 根据提示找到出错行;
2. xml 布局文件中,id不能大写;
3. 资源名不能大写!
4. 控件名称首字母要大写:< V iew
5. View划横线:用的是 background如果你从中有所收获的话,请给我点个赞吧!????
六、fragment 和 Framelayout
学习资源来自 郭神《第一行代码Ⅱ》4.2.2 动态加载碎片 P148
原图如***意右边半拉):
设置了点击事件,当点击button时,会动态载入碎片:
main_activity.xml 使用 <FrameLayout 布局时,得到的是正常的结果:
如果使用 fragment 碎片;得到的结果没有用新界面完全代替就界面,如下:
原因:
a. 因为默认的这层 right_fragment,使用的 linear layout 填充的,而这个layout里面只有一个text view,当你设置的点击事件直接使用碎片 fragment ,来动态加载碎片时,就只能在这个textview之下。
b. 要想动态加载碎片,就必须用另一个 FrameLayout 替换 LinearLayout,而后往 layout 中填充碎片。到此问题解决。
七、关于广播接收器的注册销毁
学习资源来自 郭神《第一行代码Ⅱ》5.5 最佳实践 P190 下
关于广播接收器的注册和销毁
- 广播接收器都是在 .onCreate() 中注册,在 .onDestroy() 中销毁;
- 但是本次实例,是要接受一个,强制下线的广播,只需要保证:处在栈顶位置的活动能接收到广播,非栈顶活动不需要接受;
- 所以本处用到了 activitycollect 和 BaseActivity 写的十分巧妙;来看一下 activity 的生命周期
八、一些小的注意事项
-
代码顺序,由上而下一定要有逻辑,.findViewById() 一定要先写,不然程序闪退。
-
学习存储的时候,因为无法使用DDMS查看手机的文件,而大费周章,原来就在 AS右下边有一个竖条形的键,就是打开文件存储的快捷方式。
-
manifest 中申请权限;一定要加 uses- uses- permission android:name=“android.permission.READ_CONTACTS”
-
BUG :关于 String 判空
错误: if (mResponseData.equals(null) || mResponseData.length() == 0) { 正确: if (mResponseData == null || mResponseData.equals("")) { 或者: if (!TextUtils.isEmpty(restoreText)) {
-
真机安装 apk 失败;在 gradle.properties 文件添加一句
android.injected.testOnly = false
-
java生成随机数有两种方法:
1、使用Math方法, int num = (int) (Math.random() * 15); (int) (Math.random() * num) //生成的是 0 ~ num-1 (int) (Math.random() * num + 1) //得到的是 1 ~ num 2、使用Random方法, Random random = new Random(); int length = random.nextInt(20) + 1;
-
自定义控件使用:
a. 编写 title.xml 文件; b. 编写自定义控件 类 在构造器中引入.xml LayoutInflater.from(context).inflate(R.layout.title, this); c. 在需要引用自定义控件的 xml 中引用(LinearLayout); <com.example.myapplication200122.TitleLayout ...
-
碎片的使用:
a. 编写布局 fragment.xml; b. 编写碎片 类 ; 在 .onCreate() 中使用 .inflate() 将碎片布局引入; View view = inflater.inflate(R.layout.fragment, container, false); c. 在需要使用碎片的 xml 中使用: <fragment android:name="com.example.fragmenttest.LeftFragment" ...
-
View 和ViewGroup 的区别
首件删除了笔记,现场直编……- 如果点击事件出问题,不响应或者响应其他控件时;应该 检查 xml 的布局,是否控件被覆盖;
- View 不能对其子空间进行操作,而 ViewGroup 可以,所以如果出现,动画已经从页面消失,而仍然响应点击;可以考虑
a. 把 View 更改成 ViewGroup ,然后遍历其子控件,当子控件消失设置其不可点;
b. 或者使用 属性动画(ObjectAnimator) 代替 值动画;
-
Android编译出错:
app:checkDebugDuplicateClasses
;检查是不是依赖包重复了;
九、数据库学习中遇见的BUG
-
先看代码:
报错:org.litepal.exceptions.DatabaseGenerateException: can not find a class named com.coolweather.android.db.Province 问题在于:数据库知识掌握不扎实;litepal.xml 文件中结构。如此 stupid 问题…… <litepal> <dbname value="cool_weather" /> <version value="1" /> <list> <mapping class="com.example.coolweather.db.Province" /> //放数据库所在 包名 <mapping class="com.example.coolweather.db.City" /> <mapping class="com.example.coolweather.db.County" /> </list> </litepal>
这是因为数据库中定义的名称和 .java 文件中名称不一致,找不到;
-
学习资源来自 郭神《第一行代码Ⅱ》14.5.3 将天气显示到界面上 P520
报错:Attempt to read from field 'java.lang.String com.example.coolweather.gson.Basic.cityName' on a null object reference java.lang.NullPointerException: Attempt to read from field 'java.lang.String com.example.coolweather.gson.Basic.cityName' on a null object reference
这是因为:在JSON中的一些字段可能不太适合直接作为java字段来命名,因此使用了 @SerializedName 注解的方式来让JSON 字段和Java字段之间建立映射关系;而JSON的数据是键值对的格式存在的,我们在Json格式文件中写的 键,和java文件中的取值 键 不对应;所以无法获取到对应的值。
十、inflate 方法
- 介绍
LayouInflater 中 inflate 方法两个参数和三个参数 LayoutInflater.from(RecylerActivity.this).inflate(R.layout.my_text_view,viewGroup,false); View.inflate(RecylerActivity.this, R.layout.my_text_view, null);
- 如果我们采用
convertView = inflater.inflate(R.layout.item_list, null);
方式填充视图,item布局中的根视图的layout_XX属性会被忽略掉,然后设置成默认的包裹内容方式; - 如果要保证item的视图中的参数不被改变,我们需要使用
convertView = inflater.inflate(R.layout.item_list, parent,false);
进行填充; - 除了这种方式,我们还可以设置item布局的根视图为包裹内容,然后设置内部控件的高度等属性,这样就不会修改显示方式。
总之推荐用inflater.inflate(R.layout.item, parent, false);
关于这节内容你应该是看不懂,推荐你看: inflate方法两个参数和三个参数的区别;.
如果你从中有所收获的话,请帮我点赞收藏分享鼓励我吧!????