飞飞的AI实验室

用AI放大灵感,把想法变成作品。

如题,今天开发Android串口时的使用android-serialport-api开源库,集成到项目中,然后就崩了,出现了下面的错误:

java.lang.UnsatisfiedLinkError: dlopen failed: /data/app/com.../lib/arm/libavcodec.so: has text relocations

从字面的意思大概看出来是:.so库找不到了重定向了

解决方法:

参考:

https://stackoverflow.com/questions/32346402/libavcodec-so-has-text-relocations

https://stackoverflow.com/questions/22577315/warning-linker-app-process-has-text-relocations-this-is-wasting-memory-and-is

https://stackoverflow.com/questions/44870554/ndk-15-breaks-serial-port-library

Thanks.

阅读全文 »

点app运行时报如下错:

1
Error:please select android sdk

且app module上打了个红叉,无法点击运行

提示找不到SDK

打开app.iml文件修改如下:
删除旧的,添加新的一行:

这里写图片描述

为方便大家直接复制下面的:

1
<orderEntry type="jdk" jdkName="Android API 27 Platform" jdkType="Android SDK" />

修改完成后rebuild

app 上的红叉消失,显示正常,点击运行,ok

阅读全文 »

楼主在编译一个 module 时,遇到了如下错误一直编译不过去

报错如下:

1
Failed to resolve com.android.support

刚开始自己写了一个 module demo 编译、运行都没有问题,然后又新建了一个 module,因为在新建之前看到编译好的 module 中有个 xml 文件,感觉命名不好,就 Refactor -> Rename 了一下,重命名了一下文件,一般在重命名的时候 AS 会弹出提示你是否在调用的地方也进行重命名,结果我就直接一路Refactor了,因为之前也是这样修改的,没有出过问题,然后在编译的时候就出现了上面的错误,然后定位到这一行依赖这里:

1
implementation 'com.android.support:appcompat-v7:27.1.1'

我看了一下,毛线,这是系统生成的还能写错?为了不打脸,我还是复制了一行好的比对了一下,没有问题的,我看了一下网络,网络也没有问题啊,这不科学呀,懵逼中…

于是乎,打开百度,输入如上错误,点击搜索,看到了一篇博主的文章:

https://blog.csdn.net/mhl18820672087/article/details/78385361

我看了一下,我的构建版本的工具是没有任何问题的,因为其他 module 都能编译过,就这一个 module 编译不通过,任然没有解决我的问题,打开我编译不过的 module 的 build.gradle 文件,细心的我发现了一个问题,看下图标红的地方:

这里写图片描述

阅读全文 »

初学者强烈推荐廖雪峰老师的 Git 系列教程,通俗易懂,点击此处即可开始学习

前言

我们为什么要从命令行学起?

想象一个场景,假设你在一台 CentOS7 的服务器上要使用 Git 拉取代码你怎么操作?显而易见,你是需要通过 Git 命令来拉取代码的,一方面使用 git 命令执行的效率很高,另外一方面通过 git 命令我们可以更深刻理解 git 的原理。

当我们学会了命令之后,我们再去学习各种 GUI 界面化的 Git 工具就很 easy 了,只要稍微花点时间熟悉下就可以了,反过来就没那么容易了。

1.安装Git

2.配置全局用户Name和E-mail

1
2
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"

如果想为某个仓库单独配置用户名和 email 也是可以的,去掉 –global 参数即可:

阅读全文 »

工作之余或者周末感觉无聊?不知道干什么?想继续提高技术,但是不知道做什么的同学,看过来,不妨利用闲暇时间来撸几个 GitHub 上还不错的开源项目,本文推荐的开源项目比较适合新手、及对MVP设计模式不太熟练的同学练习之用,下面逐一进行简单介绍。

1.ZhiHuMVP

一款采用 MVP 模式的仿知乎客户端。

本项目包含以下知识点:

  • MVP架构思想
  • Retrofit RESTful API 框架的配合
  • RxJava 响应式编程
  • Butter Knife:通过注解绑定 View
  • 夜间模式切换

效果图:

这里写图片描述

https://github.com/fangx/ZhiHuMVP

2.ColorfulNews

一个 Material Design 风格的新闻阅读 App,采用 MVP 模式,基于 Dagger2+RxJava+Retrofit2进行开发。

阅读全文 »

今天使用Fragment时报如下图错误:

这里写图片描述

分析原因

之所以报该错误,是因为 Fragment 事务是全局的变量,只能commit一次。

解决方法:

将获取Fragment事务定义为局部变量,每次提交时都去获取新的事务去commit即可。

阅读全文 »

一、内存简介

根据《Java虚拟机规范(第2版)》的规定,Java虚拟机所管理的内存将会包括以下几个运行时数据区域,如下图所示:

经常人把Java内存区分为堆内存(Heap)和栈内存(Stack),这种分法比较粗糙,Java内存区域的划分实际上远比这复杂。这种划分方式的流行是因为大多数程序员最关注的、与对象内存分配关系最密切的内存区域是这两块。
通常所说的堆(Heap),此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
通常所说的栈(Stack),是指虚拟机栈。虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。因此局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。 方法执行完,自动释放。
方法区(Method Area)用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

二、垃圾回收机制

垃圾回收(Garbage Collection,GC):在程序的运行环境中,JVM(Java虚拟机)提供了一个系统级的垃圾回收器线程,它负责自动回收那些无用对象所占用的堆内存。这种内存回收的过程被称为垃圾回收。

Java语言中,内存回收任务由JVM来担当。
Java的垃圾回收机制是JVM提供的能力,由单独的系统级垃圾回收线程在空闲时间以不定时的方式动态回收无任何引用的对象占据的堆内存空间。

(1)程序只能决定一个对象不再被任何引用变量引用,使得它成为可以被回收的垃圾。
类比:决定什么样的东西扔掉

(2)不能决定垃圾回收的时间。垃圾回收器作为低优先级线程独立运行。在任何时候,程序都无法迫使垃圾回收器立即执行垃圾会后操作。
类比:居民把无用物品放在指定的地方,清洁工人会把它收拾走。但垃圾被收走的时间,居民是不知道的,也无需了解。

(3)程序中可调用System.gc()或Runtime.gc()方法提示垃圾回收器尽快执行垃圾回收操作,但是不能保证调用后垃圾回收器会立即执行垃圾回收。
类比:小区垃圾成堆时,居民打电话给环保局,催促清洁工尽快来处理垃圾。但是清洁工不一定立即就来了,也有可能很长时间后再来。

阅读全文 »

1.思路

  1. 通过年份区分出是闰年还是平年,平年 2 月 28 年,闰年 2 月 29 天;
  2. 1、3、5、7、8、10、12 月份 31 天其余月份均为 30 天;
  3. 然后将每个月的天数相加即可,注意如果输入的是 12 月份,则是从 11 月份往前累加到1月份,1月份加的是输入的天数;

2.实现

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import java.util.Scanner;

/**
* Created by xpf on 2018/6/22 :)
* GitHub:xinpengfei520
* Function:
*/
public class CalculateUtils {

/*平年二月28天*/
private static final int DAYS_28 = 28;
/*闰年二月29天*/
private static final int DAYS_29 = 29;
/*除了31天的月份其他均为30天*/
private static final int DAYS_30 = 30;
/*1、3、5、7、8、10、12月份31天*/
private static final int DAYS_31 = 31;

public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Please input year:");
int year = input.nextInt();
System.out.println("Please input month:");
int month = input.nextInt();
System.out.println("Please input day:");
int day = input.nextInt();

int daysInYear = getDaysInYear(year, month, day);
System.out.println("daysInYear:" + daysInYear);
}

/**
* get days in this year
*
* @param year
* @param month
* @param day
* @return
*/
public static int getDaysInYear(int year, int month, int day) {
int totalDays = 0;

switch (month) {
// 12 月份加的是11月份的天数,依次类推
case 12:
totalDays += DAYS_30;
case 11:
totalDays += DAYS_31;
case 10:
totalDays += DAYS_30;
case 9:
totalDays += DAYS_31;
case 8:
totalDays += DAYS_31;
case 7:
totalDays += DAYS_30;
case 6:
totalDays += DAYS_31;
case 5:
totalDays += DAYS_30;
case 4:
totalDays += DAYS_31;
case 3:
// 判断是否是闰年
if (((year / 4 == 0) && (year / 100 != 0)) || (year / 400 == 0)) {
totalDays += DAYS_29;
} else {
totalDays += DAYS_28;
}
case 2:
totalDays += DAYS_31;
case 1: // 如果是1月份就加上输入的天数
totalDays += day;
}

return totalDays;
}
}

3.思考

因为只有2月份的天数和输入的 day 天数是不固定的,其他月份的天数是固定的,而固定的天数是可以通过输入的月份算出来,这样我们就可以这样计算:

1
2 月份的天数 + 输入的天数 + 计算出来的固定天数

如果大家还有其他的更好的优化的都可以在下面评论。

阅读全文 »

我们都知道把一个基本数据类型转为 String 类型,一般有三种方式,例如:有一个 Integer 型数据 a,可以使用i.toString()、String.valueOf(i)、i+”” 三种方式,三种方式的效率如何,接下来我们做一个小测试:

1.测试代码如下:

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
/**
* 把一个基本数据类型转为字符串
*/
private void testExecuteTime() {
int loopTime = 100000;
//Integer i = 0;
Long i = 0L;
long startTime;

startTime = System.currentTimeMillis();
for (int j = 0; j < loopTime; j++) {
String str = String.valueOf(i);
}
Log.e("TAG", "String.valueOf():" + (System.currentTimeMillis() - startTime) + "ms");

startTime = System.currentTimeMillis();
for (int j = 0; j < loopTime; j++) {
String str = i.toString();
}
Log.e("TAG", "Integer.toString():" + (System.currentTimeMillis() - startTime) + "ms");

startTime = System.currentTimeMillis();
for (int j = 0; j < loopTime; j++) {
String str = i + "";
}
Log.e("TAG", "i + \"\":" + (System.currentTimeMillis() - startTime) + "ms");
}

2.测试结果

这里写图片描述

3.结论

把一个基本数据类型转换为String,使用**.toString()是最快的方式、String.valueOftoString差不多、数据+””**的效率最慢,其实这些执行都是毫秒级,现在处理器的性能都比较强悍,其实影响不大,对于用户来说,没有什么感觉,但是我们可以再写代码的时候养成一个良好的习惯,有时候不用抠这么细,毕竟不是底层的代码,应用层,主要先以实现业务功能为主,这样后续有时间可以优化,记住一点:大行不顾细谨,大理不辞小让!

阅读全文 »

##1.设置分割的颜色和高度

divider设置分割线的颜色属性;

dividerHeight设置分割线的高度;

1
2
3
4
5
6
7
8
9
<ListView
android:id="@+id/listView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/margin_14dp"
android:layout_marginRight="@dimen/margin_14dp"
android:layout_marginTop="@dimen/margin_8dp"
android:divider="@color/transparent"
android:dividerHeight="8dp" />

##2.去掉分割线

1.在代码中设置:setDriver(null);

2.或者在布局文件中设置:android:divider=”@null”;

3.如果没有背景也可将divider设置为透明也可以实现隐藏分割线的效果,但是这种方式分割线还是存在的,并且占了一定的高度,只是隐藏显示了而已;

更多关于ListView的文章请参考:

http://blog.csdn.net/bdmh/article/details/39522071

阅读全文 »
0%