Tim

一枚野生程序员~

  • 主页
  • 分类
  • 标签
  • 归档
  • 关于
所有文章 工具

Tim

一枚野生程序员~

  • 主页
  • 分类
  • 标签
  • 归档
  • 关于

Android学习日志

阅读数:次 2018-04-23
字数统计: 3.3k字   |   阅读时长≈ 14分

常见布局

相对布局 RelativeLayout

  • 组件默认左对齐、顶部对齐

  • 设置组件在指定组件的右边
    android:layout_toRightOf="@id/tv1"

  • 设置在指定组件的下边
    android:layout_below="@id/tv1"

  • 设置右对齐父元素
    android:layout_alignParentRight="true"

  • 设置与指定组件右对齐
    android:layout_alignRight="@id/tv1"

线性布局LinearLayout

  • 指定各个节点的排列方向

  • 设置右对齐
    android:layout_gravity="right"

  • 当竖直布局时,只能左右对齐和水平居中,顶部底部对齐竖直居中无效

  • 当水平布局时,只能顶部底部对齐和竖直居中

  • 使用match_parent时注意不要把其他组件顶出去

  • 线性布局非常重要的一个属性:权重
    android:layout_weight="1"

  • 权重:按比例分配屏幕的剩余宽度或者高度

帧布局FrameLayout

  • 默认组件都是左对齐和顶部对齐,每个组件相当于一个div

  • 可以设置上下左右对齐,水平竖直居中,设置方式与线性布局一样
    android:layout_gravity="bottom"

  • 不能相对于其他组件布局

表格布局TableLayout

  • 每个<TableRow/>节点是一行,它的每个子节点是一列

  • 表格布局中的节点可以不设置宽高,因为设置了也无效

    • 根节点<TableLayout/>的子节点宽为匹配父元素,高为包裹内容
    • <TableRow/>节点的子节点宽为包裹内容,高为包裹内容
    • 以上默认属性无法修改
  • 根节点中可以设置以下属性,表示让第1列拉伸填满屏幕宽度的剩余空间
    android:stretchColumns="1"

绝对布局AbsoluteLayout

  • 直接指定组件的x、y坐标
    android:layout_x="144dp"
    android:layout_y="154dp"

注意:直接复制项目需要改动的地方:项目名字、应用包名、R文件重新导包

路径API说明

  • getFilesDir()得到的file对象的路径是data/data/应用包名/files

    • 存放在这个路径下的文件,只要你不删,它就一直在
  • getCacheDir()得到的file对象的路径是data/data应用包名/cache

    • 存放在这个路径下的文件,当内存不足时,有可能被删除
  • 系统管理应用界面的清除缓存,会清除cache文件夹下的东西,清除数据,会清除整个包名目录下的东西


sd卡的路径

  • 2.2之前,sd卡路径:sdcard

  • 4.3之前,sd卡路径:mnt/sdcard

  • 4.3开始,sd卡路径:storage/sdcard

  • 最简单的打开sd卡的方式
    File file = new File("sdcard/test.txt");

  • 使用api获得sd卡的真实路径,部分手机品牌会更改sd卡的路径
    Environment.getExternalStorageDirectory()

  • 判断sd卡是否准备就绪
    if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))


获取SD容量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import java.io.File;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.StatFs;
import android.text.format.Formatter;
import android.widget.TextView;

public class MainActivity extends Activity {
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
if(existSDCard()){
String available = formatSize(getAvailable());
String allSize = this.formatSize(getAllSize());
tv.setText("总空间:"+allSize+" 可用空间"+available);
}
}

//获取可用容量
private long getAvailable(){
File path = Environment.getExternalStorageDirectory();
StatFs sf = new StatFs(path.getPath());
//获取单个数据块的大小(Byte)
long blockSize = sf.getBlockSizeLong();
//获取所有数据块数
long availbleBlocks = sf.getAvailableBlocksLong();
return blockSize* availbleBlocks;
}

//获取总容量
private long getAllSize(){
File path = Environment.getExternalStorageDirectory();
StatFs sf = new StatFs(path.getPath());
//获取单个数据块的大小(Byte)
long blockSize = sf.getBlockSizeLong();
//获取所有数据块数
long allBlocks = sf.getBlockCountLong();
return blockSize*allBlocks;
}

//格式化函数
private String formatSize(long size) {
return Formatter.formatFileSize(this, size);
}

//是否挂载SD卡
private boolean existSDCard() {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
return true;
} else return false;
}
}

注意:在使用getBlockCountLong()等API的时候主要SDK的版本,SDK17是不支持getBlockCountLong()的,低版本的SDK仍然使用getBlockCount()等不带Long的
mark

测试

测试分类

  • 黑盒测试

    • 测试逻辑业务
  • 白盒测试

    • 测试逻辑方法
  • 根据测试粒度

    • 方法测试:function test
    • 单元测试:unit test
    • 集成测试:integration test
    • 系统测试:system test
  • 根据测试暴力程度

    • 冒烟测试:smoke test(例如monkey 1000:在屏幕上随机点击1000次)
    • 压力测试:pressure test

Android中的单元测试

首先要使用一个类继承自AndroidTestCast:

1
2
3
4
5
6
7
import android.test.AndroidTestCase;

public class Test extends AndroidTestCase {
public void test(){
//TODO 测试的代码或者方法
}
}

并且在中做出如下配置:

1
2
3
4
5
6
7
8
9
10
11
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="要测试的应用包名">
</instrumentation>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<!-- 只有这一个属性就是android.test.runner -->
<uses-library android:name="android.test.runner"/>
</application>

SQLite

  • 轻量级关系型数据库

  • 创建数据库需要使用的api:SQLiteOpenHelper

    • 数据库被创建时会调用:onCreate方法
    • 数据库升级时会调用:onUpgrade方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;

    public class MyOpenHelper extends SQLiteOpenHelper {

    public MyOpenHelper(Context context) {
    //参数说明:上下文、数据库名称、游标工厂(默认使用NULL)、版本(用于升级)
    super(context, "test.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
    //创建表
    db.execSQL("create table person(_id integer primary key autoincrement, name char(10), phone char(20), salary integer(10))");
    }

    //数据库升级的时候调用
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    System.out.println("数据库升级...");
    }
    }

创建数据库

1
2
3
4
//创建OpenHelper对象
MyOpenHelper oh = new MyOpenHelper(getContext(), "test.db", null, 1);
//获得数据库对象,如果数据库不存在,先创建数据库,后获得,如果存在,则直接获得
SQLiteDatabase db = oh.getWritableDatabase();
  • getWritableDatabase():打开可读写的数据库
  • getReadableDatabase():在磁盘空间不足时打开只读数据库,否则打开可读写数据库

数据库的增删改查

数据库的增删改查可以自己使用SQL语句,然后db.execSQL("SQL语句")即可完成!

注意:setup主要实现测试前的初始化工作,而teardown则主要实现测试完成后的垃圾回收等工作。

1
2
3
4
5
6
7
8
9
10
11
12
@Override
protected void setUp() throws Exception {
super.setUp();
//获取虚拟上下文对象
oh = new MyOpenHelper(getContext(), "test.db", null, 1);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
//关闭数据库
db.close();
}

使用API实现增删改查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//使用游标来逐个访问每条数据
public void select(){
Cursor cursor = db.rawQuery("select * from 表名", null);
//把指针移动至下一行
while(cursor.moveToNext()){
//先通过列名,获取列索引,然后再获取该列的内容
String str = cursor.getString(cursor.getColumnIndex("字段名1"));
String str2 = cursor.getString(cursor.getColumnIndex("字段名2"));
int str3 = cursor.getInt(cursor.getColumnIndex("字段名3"));
System.out.println(str+str2+str3);
}
}
public void insertApi(){
ContentValues values = new ContentValues();
values.put("字段1", "value");
values.put("字段2", "value");
values.put("字段3", "value");
//返回值-1,插入失败
long l = db.insert("表名", null, values);
}

public void deleteApi(){
//因为后面要传入的是对象数组
int i = db.delete("表名", "_id = ?", new String[]{"4"});
}

public void updateApi(){
ContentValues values = new ContentValues();
values.put("字段名", "value");
int i = db.update("表名", values, "_id = ?", new String[]{"1"});
}

事务

保证多条SQL语句要么同时成功,要么同时失败,失败的话会发生回滚!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void transaction(){
try{
//开启事务
db.beginTransaction();

//TODO 修改表数据...

//设置事务执行成功,提交时如果这行代码没有执行过,就会回滚
db.setTransactionSuccessful();
}
catch (Exception e) {
//这里的异常必须要捕获
e.printStackTrace();
}
finally{
//关闭事务,提交数据
db.endTransaction();
}
}

ListView

  • 用于显示列表

  • MVC结构

    • M:model模型层,要显示的数据 ————people集合
    • V:view视图层,用户看到的界面 ————ListView
    • c:control控制层,操作数据如何显示 ————adapter对象
  • 每一个条目都是一个View对象

    BaseAdapter

  • 必须实现的两个方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    // 适配器类
    class MyAdapter extends BaseAdapter {
    // 系统调用:获取模型层数据的数量
    @Override
    public int getCount() {
    return list.size();
    }

    // 系统调用:获取要显示至ListView的View对象
    // convertView:系统之前缓存的条目
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    People p = list.get(position);
    View view = null;
    if (convertView == null) {
    // 把布局文件填充为view对象(看源码,这就是三种方式)
    // LayoutInflater layIn = LayoutInflater.from(MainActivity.this);
    // LayoutInflater layIn = (LayoutInflater)getSystemService("layout_inflater");
    // view = layIn.inflate(R.layout.item_listview,null);
    view = View.inflate(getApplicationContext(),R.layout.item_listview, null);

    } else {
    view = convertView;
    TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
    TextView tv_phone = (TextView) view.findViewById(R.id.tv_phone);
    TextView tv_sa = (TextView) view.findViewById(R.id.tv_sa);

    tv_name.setText(p.getName());
    tv_phone.setText(p.getPhone());
    tv_sa.setText(p.getSalary());
    }
    return view;
    }
    }

屏幕上能显示多少个条目,getView方法就会被调用多少次,屏幕向下滑动时,getView会继续被调用,创建更多的View对象显示至屏幕

条目的缓存

当条目划出屏幕时,系统会把该条目缓存至内存,当该条目再次进入屏幕,系统在重新调用getView时会把缓存的条目作为convertView参数传入,但是传入的条目不一定是之前被缓存的该条目,即系统有可能在调用getView方法获取第一个条目时,传入任意一个条目的缓存!

ArrayAdapter

在条目中显示一个字符串

1
2
3
4
5
String[] objects = new String[]{"AAA","BBB","CCC"};
ListView lv = (ListView) findViewById(R.id.lv);
//arg1:指定要填充的布局文件
//arg2:指定文本显示至哪一个文本框内
lv.setAdapter(new ArrayAdapter<String>(this, R.layout.item_array, R.id.tv_name, objects));

SimpleAdapter

可在条目中显示多种数据

要显示的数据封装在List中,集合的每一个元素存放的是一个条目会显示的数据,因为可能会有多种数据,而集合的泛型只能指定一种数据,所以把数据先存放在Map中,在把Map放入List中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView)findViewById(R.id.lv);

//把每个条目需要处理的所有数据封装至map中,在把map封装至list中
//这样就保证了list每个元素都包含了一个条目需要的所有数据
List<Map<String, Object>> data = new ArrayList<Map<String,Object>>();
Map<String, Object> m1 = new HashMap<String, Object>();
m1.put("name","AAA");
m1.put("Photo",R.drawable.a);
data.add(m1);

Map<String, Object> m2 = new HashMap<String, Object>();
m2.put("name","BBB");
m2.put("Photo",R.drawable.b);
data.add(m2);

Map<String, Object> m3 = new HashMap<String, Object>();
m3.put("name","CCC");
m3.put("Photo",R.drawable.c);
data.add(m3);

lv.setAdapter(new SimpleAdapter(MainActivity.this, data, R.layout.item_listview,
new String[]{"name","Photo"} ,
new int[]{R.id.name, R.id.iv}));

Android项目的目录结构

1、 Activity:应用被打开时显示的界面
2、 src:项目代码
3、R.java:项目中所有资源文件的资源id
4、 Android.jar:Android的jar包,导入此包方可使用Android的api
5、libs:导入第三方jar包
6、assets:存放资源文件,比方说mp3、视频文件
7、bin:存放编译打包后的文件
8、 res:存放资源文件,存放在此文件夹下的所有资源文件都会生成资源id
9、 drawable:存放图片资源
10、 layout:存放布局文件,把布局文件通过资源id指定给activity,界面就会显示出该布局文件定义的布局
11、 menu:定义菜单的样式
12、Strings.xml:存放字符串资源,每个资源都会有一个资源

JVM 和DVM(Dalvik)的区别

Android的新虚拟机ART:
Dalvik:应用每次运行的时候,字节码都需要通过及时编译转换为机器码,这会拖慢应用的启动速度
ART:应用在第一次安装的时候,字节码会预先编译成机器码,使其成为真的本地应用,应用的启动和执行速度都会显著提升

adb指令:

adb install D:\weibo.apk 安装apk
adb uninstall 包名 卸载apk
adb kill-server 杀死adb进程
adb start-server 开启adb进程
adb devices 列举与开发环境连接的Android设备列表
adb shell 进入Android命令行执行Linux指令

一个windows指令:netstat -ano 查看端口号的占用情况(adb进程在5037端口,如果端口被占用则会导致adb启动失败)

调用系统的拨号Activity

1
2
3
4
5
6
7
8
9
10
11
//点击按钮拨打电话
public void call(View v) {
//先创建一个意图对象
Intent intent = new Intent();
//设置动作,打电话
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" + phone));
//把意图告诉系统
startActivity(intent);

}

短信发送的API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void send(View v) {
String mmsg = "Text";
String phone = "15291418231";
// 直接使用发送信息的API
SmsManager sm = SmsManager.getDefault();
// 将长短信截为短的短信
ArrayList<String> message = sm.divideMessage(mmsg);
// 截断后分条发送
for (String mmsg_str : message) {
// 目标号码、
// 短信中心号码(null使用默认)
// 短信文本
// 发送成功或失败的广播
// 对方接收成功的广播
sm.sendTextMessage(phone, null, mmsg_str, null, null);
}
}

点击事件的四种写法

  • 定义一个MyListener实现onClickListener接口
  • 定义一个匿名内部类实现onClickListener接口
  • 让当前activity实现onClickListener接口
  • 给Button节点设置onClick属性,然后在activity中定义跟该属性值同名的方法

px与dp:dp跟密度有关,px是像素,使用dp更容易做屏幕适配

赏

谢谢你请我喝咖啡

支付宝
微信
  • 本文作者: Tim
  • 本文链接: https://zouchanglin.cn/3231229173.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。转载请注明出处!
  • Android
  • 移动开发

扫一扫,分享到微信

回溯思想解决迷宫问题
Linux常用命令
  1. 1. 常见布局
    1. 1.1. 相对布局 RelativeLayout
    2. 1.2. 线性布局LinearLayout
    3. 1.3. 帧布局FrameLayout
    4. 1.4. 表格布局TableLayout
    5. 1.5. 绝对布局AbsoluteLayout
  2. 2. 路径API说明
  3. 3. sd卡的路径
  4. 4. 获取SD容量
  5. 5. 测试
    1. 5.1. 测试分类
    2. 5.2. Android中的单元测试
  6. 6. SQLite
    1. 6.1. 创建数据库
    2. 6.2. 数据库的增删改查
    3. 6.3. 使用API实现增删改查
    4. 6.4. 事务
  7. 7. ListView
    1. 7.1. BaseAdapter
    2. 7.2. 条目的缓存
    3. 7.3. ArrayAdapter
    4. 7.4. SimpleAdapter
  8. 8. Android项目的目录结构
  9. 9. JVM 和DVM(Dalvik)的区别
  10. 10. adb指令:
  11. 11. 调用系统的拨号Activity
  12. 12. 短信发送的API
  13. 13. 点击事件的四种写法
© 2017-2021 Tim
本站总访问量次 | 本站访客数人
  • 所有文章
  • 工具

tag:

  • 生活
  • Android
  • 索引
  • MySQL
  • 组件通信
  • Nginx
  • JavaSE
  • JUC
  • JavaWeb
  • 模板引擎
  • 前端
  • Linux
  • 计算机网络
  • Docker
  • C/C++
  • JVM
  • 上传下载
  • JavaEE
  • SpringCloud
  • Golang
  • Gradle
  • 网络安全
  • 非对称加密
  • IDEA
  • SpringBoot
  • Jenkins
  • 字符串
  • vim
  • 存储
  • 文件下载
  • Mac
  • Windows
  • NIO
  • RPC
  • 集群
  • 微服务
  • SSH
  • 配置中心
  • XML
  • Chrome
  • 压力测试
  • Git
  • 博客
  • 概率论
  • 排序算法
  • 分布式
  • 异常处理
  • 文件系统
  • 哈希
  • openCV
  • 栈
  • 回溯
  • SpringCore
  • 流媒体
  • rtmp
  • 面向对象
  • Vue
  • ElementUI
  • 软件工程
  • 异步
  • 自定义UI
  • ORM框架
  • 模块化
  • 交互式
  • Jsoup
  • Http Client
  • LRUCache
  • RabbitMQ
  • 消息通信
  • 服务解耦
  • 负载均衡
  • 权限
  • 多线程
  • 单例模式
  • Protobuf
  • 序列化
  • Python
  • m3u8
  • 堆
  • 二叉树
  • 自定义View
  • 观察者模式
  • 设计模式
  • 线程池
  • 动态扩容
  • 高可用
  • GC
  • ffmpeg
  • SpringMVC
  • REST
  • Redis
  • 缓存中间件
  • UML
  • Maven
  • Netty
  • 高性能网络
  • IPC通信
  • IO
  • Stream
  • 发布订阅
  • SQLite
  • Hash
  • 集合框架
  • 链表
  • Lambda
  • 汇编语言
  • 组件化
  • Router
  • 开发工具

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia-plus根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • 思维导图
  • PDF工具
  • 无损放大
  • 代码转图
  • HTTPS证书