Zhujiaqqq Blog


  • 首页

  • 关于

  • 标签

  • 分类

Mac中sftp使用

发表于 2019-06-09 | 分类于 Tools

使用的工具

系统自带的Terminal(终端)

开启sftp

点击:

Shell->新建远程连接

配置

  • 服务:安全文件传输(sftp)

  • 服务器:输入自己需要连接的服务器IP

  • 用户:输入自己需要连接的服务器用户名

  • 点击连接

  • 输入密码

sftp常用指令:

  • pwd/lpwd

    查看远程/本地的当前目录

  • ls/lls

    查看远程/本地当前目录下的文件及文件夹

  • put xxx

    将本地xxx上传到远程端

  • get xxx

    将远程端xxx下载到本地

  • !command

    以!开头的指令为本地指令,没有!的指令为远程端指令

  • exit/quit

    退出sftp模式

ShadowSocks服务器搭建

发表于 2019-06-09 | 分类于 Tools

硬件需求

一个云服务器,能访问国际网络

安装ShadowSocks

  • 安装pip工具
    • yum install python-pip
  • 通过pip安装ShadowSocks
    • pip install shadowsocks

配置ShadowSocks服务

  1. 新建一个ShadowSocks的配置文件:/etc/shadowsocks.json
  2. 写入配置:
1
2
3
4
5
6
7
8
9
10
11
{
"server":"0.0.0.0",
"server_port":443,
"local_address":"127.0.0.1",
"local_port":1080,
"password":"your-passwd",
"timeout":300,
"method":"aes-256-cfb",
"fast_open":false,
"workers":5
}

启动ShadowSocks服务:

ssserver -c /etc/shadowsocks.json -d start

关闭ShadowSocks服务命令:ssserver -c /etc/shadowsocks.json -d stop

合并两个有序链表

发表于 2019-05-26 | 分类于 LeetCode

题目:(LeetCode.21)合并两个有序链表

将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例:

1
2
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

解法

这个一个简单的链表操作问题。在两个输入链表均不为空的时候,将较小的一个元素插入新链表中,并将那个较小链表的表首先后移一位。

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
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
int rootVal;
if (l1.val < l2.val) {
rootVal = l1.val;
l1 = l1.next;
} else {
rootVal = l2.val;
l2 = l2.next;
}
ListNode root = new ListNode(rootVal);
ListNode temp = root;
for (; ; ) {
if (l1 != null && l2 != null) {
if (l1.val < l2.val) {
temp.next = new ListNode(l1.val);
l1 = l1.next;
} else {
temp.next = new ListNode(l2.val);
l2 = l2.next;
}
temp = temp.next;
}else {
if (l1 == null) {
temp.next = l2;
}
if (l2 == null) {
temp.next = l1;
}
break;
}
}
return root;
}

class ListNode {
int val;
ListNode next;

ListNode(int x) {
val = x;
}
}
}

如何在代码的任意位置为当前Activity添加View

发表于 2019-05-25 | 分类于 Android

获取当前Activity

使用ActivityLifecycleCallbacks回调获取create的Activity对象

添加View

使用Activity.addContentView(View view, ViewGroup.LayoutParams params)

移除View:Activity.removeContentView(View view)

将Content获取,在Content中手动添加View:

Content view 的ID为:android:id/content

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ActivityExt {
private final Activity mActivity;
private final ViewGroup mViewGroup;

public ActivityExt(Activity activity) {
mActivity = activity;
mViewGroup = activity.findViewById(android.R.id.content);
}

public void addContentView(View view, ViewGroup.LayoutParams params) {
mViewGroup.addView(view, params);
}

public void removeContentView(View view) {
mViewGroup.removeView(view);
}
}

在整个屏幕中添加View

上面说的addContentView是在Content中添加View,有一定的局限性,如果想在整个屏幕中添加View,不如说水印、护眼壁纸等,就需要将content上面的actionBar、stateBar也添加View。

整个屏幕中能看见的部分都来自一个总的view——DecorView

  • 获取DecorView:FrameLayout decorView = (FrameLayout) getWindow().getDecorView();
  • DecorView是一个FrameLayout,在里面直接addView(View view, ViewGroup.LayoutParams params)就可以添加View。

添加的View在整个FrameLayout布局的最上层,覆盖在Content的上面。如果添加的View有事件拦截的话,正常显示的Activity将无法获取事件消息。

添加View的需求评估

一般情况下,在Activity中手动添加View都是对整个app的页面统一添加,所以在需求评估时候需要确认使用场景,给出合理的方案,大型的app页面众多,不同的开发者为实现不同的效果,可能会对页面做不同的修改,全局添加的view在部分页面会出现崩溃。

计数质数

发表于 2019-05-04 | 分类于 LeetCode

题目:(LeetCode.204)统计所有小于非负整数 n 的质数的数量

1
2
3
4
> 输入: 10
> 输出: 4
> 解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
>

质数:在大于1的自然数中,除了1和它本身以外不再有其他因数。算法中的基本判断思路是:对于正整数n,如果用2到 $\sqrt n$ 之间到所有整数去除,均无法整除,则n为质数

暴力解法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public int countPrimes(int n) {
int count = 0;
for (int i = 1; i < n; i++) {
if (isPrime(i)) {
count++;
}
}
return count;
}

private boolean isPrime(int n) {
if (n <= 3) {
return n > 1;
}

for (int i = 2; i <= Math.sqrt(n); i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
}

这种方法逻辑原理没有问题,但是时间复杂度较高,在LeetCode中提交显示时间超时(Time Limit Exceeded)。


通过思考质数的定义,可以发现,如果某一个数为质数,那么这个数的任何整数倍数都不是质数,所以可以通过递推的方式进行判断。

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
class Solution {
public int countPrimes(int n) {
if (n < 3) {
return 0;
}
int[] nums = new int[n];
nums[0] = 1;
nums[1] = 1;
for (int i = 2; i < Math.sqrt(n); i++) {
if (nums[i] == 0) {
for (int j = i * i; j < n; j += i) {
nums[j] = 1;
}
}
}

int count = 0;
for (int i = 0; i < n; i++) {
if (nums[i] == 0) {
count++;
}
}
return count;
}
}

Serializable和Parcelable的区别

发表于 2019-04-22 | 分类于 Android

序列化实现的不同

  • Serializable

    继承Serializable接口,定义一个 serialVersionUID 常量:

    private static final long serialVersionUID = -7060210544600464481L;

  • Parcelable

    继承Parcelable接口,复写三个方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Override
    public int describeContents(){
    return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags){
    out.writeString(bookName);
    ...
    }

    @Override
    public Book createFromParcel(Parcel in){
    return new Book(in);
    }

性能差异

  • Serializable是通过反射机制实现序列化的,在序列化操作的时候会产生大量的临时变量,导致GC频繁调用。

  • Parcelable是以Ibinder作为信息载体,所有在内存中序列化开销较小。

总结

Serializable使用方便,但系统开销较大;Parcelable实现比较麻烦,但开销较小,但是无法实现数据持久化,因为不同的Android版本中,Parcelable可能会不同(观点存疑)。

参考:

  • Android中Serializable和Parcelable序列化对象详解

  • ANDROID:SERIALIZABLE和PARCELABLE的持久化保存

主线程的Looper为什么不会导致应用ANR

发表于 2019-04-18 | 分类于 Android

ANR类型

  • Service timeout:
    • 前台服务 20s
    • 后台服务 200s
  • BroadcastQueue timeout:
    • 前台广播10s
    • 后台广播60s
  • ContentProvider timeout:10s
  • InputDispatching timeout:5s

1
2
3
4
5
6
7
8
9
10
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
if (proc.executingServices.size() == 0 || proc.thread == null) {
return;
}
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc;
mAm.mHandler.sendMessageDelayed(msg,
proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
}

SERVICE_TIMEOUT时间后会执行这个msg,导致ANR。

主线程究竟在干什么

ActivityThread.main()中:Looper.loop();

一直在死循环!!!

ANR只是针对某些情况没有及时响应抛出的异常。这种异常是通过handler发送的消息抛出的。

looper handler messageQueue是整个线程运作的维持。

ANR是针对组件长时间未响应而抛出的异常。

两者不是统一层次的。

Looper为什么不会导致CPU占用率高

虽然Looper.loop()是一个死循环,但是在循环中会通过messageQueue.next()方法获取message,此时,如何消息队列为空,那么整个线程会进入阻塞状态,不会消耗cpu时间片。

什么情况导致内存泄漏?

发表于 2019-04-16 | 分类于 Android

内存泄漏是生命周期较长的对象持有生命周期较短的对象的所引用

举个例子,如果一个 Activity 被一个单例对象所引用,那么当退出这个 Activity 时,由于单例的对象依然存在(单例对象的生命周期跟整个 App 的生命周期一致),而单例对象又持有 Activity 的引用,这就导致了此 Activity 无法被回收,从而造成内存泄漏。

  • 单例造成的内存泄漏

    单例对象中有Context引用,这个Context不应该是Activity,而应该是applicationContext引用,这样就不会造成内存泄漏。

  • 非静态内部类造成的内存泄漏

    非静态内部类会默认持有外部类的应用。此时,如果这个内部类的实例是静态实例,则会与整个app的生命周期相同,当外部类生命周期结束时,还被内部类引用,则无法被回收,造成内存泄漏。

    解决办法:使内部类的实例不为静态实例或者使内部类变为静态内部类(不会持有外部类的引用)。

  • Handler 或 Runnable 作为非静态内部类

    handler 和 runnable 都有定时器的功能,当它们作为非静态内部类的时候,同样会持有外部类的引用,如果它们的内部有延迟操作,在延迟操作还没有发生的时候,销毁了外部类,那么外部类对象无法回收,从而造成内存泄漏。

    解决办法:把 Handler 和 Runnable 定义为静态内部类,这样它们就不再持有 MainActivity 的引用了,从而避免了内存泄漏,最好再在 onDestory 调用 handler 的 removeCallbacks 方法来移除 Message。

  • 其他的内存泄漏情况

    比如 BraodcastReceiver 未取消注册,InputStream 未关闭等,这类内存泄漏非常简单,只要在平时写代码时多多注意即可避免。

  • MVP架构中的内存泄漏

    Presenter持有iview的引用,在activity/fragment生命周期结束后,presenter还在做耗时操作就会出现内存泄漏。

    解决办法:在activity/fragment的onDestroy()方法中将presenter的view对象置空,使得presenter不再持有activity/fragment的引用。

OOM是什么?什么情况导致OOM?有什么解决方法可以避免OOM?

发表于 2019-04-11 | 分类于 Android
  • OOM是Java 异常,java.lang.OutOfMemoryError

  • 导致OOM的原因:

    • 加载大图片导致内存溢出
    • 大量的内存泄漏
  • 解决方法:

    • 使用更轻量的数据结构
    • 避免在Android里面使用Enum
    • 减少Bitmap对象的内存占用:缩放比例、解码格式
    • 使用更小的图片
    • 复用系统自带的资源
    • ListView、GridView中对ConvertView的复用,ViewHolder内部类使用
    • 避免onDraw方法中执行对象的创建
    • 用StringBuilder进行拼接
    • 注意Activity的泄漏:内部类引用导致Activity泄漏、Activity的Context被传递到其他实例中,可能导致自身被引用而发生泄漏。

ANR定位和修正

发表于 2019-04-08 | 分类于 Android

定位:

结合logcat和生成在手机内部的/data/anr/traces.txt文件进行分析

修正:

  1. 运行在主线程的任何方法都要尽量少做事情,特别是Activity生命周期中关键的方法(onCreate onResume里面尽可能少去创建操作;可以采用重新开启子线程的方式,然后使用Handler+Message的方式做一些操作,比如更新主线程中的ui等)

  2. 避免BroadcastReceiver里面做耗时的操作或计算,也不能在receiver中起线程做这些任务,因为receiver的生命周期很短,10s。可以在receiver中通过Intent启动一个Service去执行耗时操作。

  3. 避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现

1…345

Zhujiaqqq

Java Android Python Algorithm and Machine learning

43 日志
6 分类
55 标签
© 2019 Zhujiaqqq
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4