OI KIWI 01-倍增

OI KIWI 倍增

思想

图片来源

查找小于limit的最大数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int maxValueInVecSmallerThenLimit(vector<int>& vec, int limit) {
int n = vec.size();
int l = 0;
int p = 1;
while(p) {
if(l + p < n && vec[l + p] < limit) {
l += p;
p <<= 1;
} else {
p >>= 1;
}
}
return vec[l];
}
阅读更多

LeetCode-36

551. 学生出勤记录 I

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
bool checkRecord(string s) {
int count = 0;
int max_seq_late = 0;
int seq_late = 0;
for(char c : s) {
if(c == 'A') count++;
if(c == 'L') {
seq_late++;
} else {
max_seq_late = max(max_seq_late, seq_late);
seq_late = 0;
}
}
max_seq_late = max(max_seq_late, seq_late);
return count < 2 && max_seq_late < 3;

}
};
  • 连续相同的值的个数
  • 统计元素出现的次数

3137. K 周期字符串需要的最少操作次数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
int minimumOperationsToMakeKPeriodic(string word, int k) {
unordered_map<string, int> subStrCount;
int len = word.length();
for(int i = 0; i < len; i += k) {
subStrCount[word.substr(i, k)]++;
}
int minOpCnt = len / k;
for(auto& ite : subStrCount) {
minOpCnt = min(minOpCnt, len / k - ite.second);
}
return minOpCnt;
}
};
  • 翻译一下规则,就是把长度为nk的字符串切割成n个长度为k的子串,一次操作可以把一个子串替换成另一个字串,求如何替换,将所有字串都相同。
  • 翻译好需求,就很清楚了,直接统计每个字串出现的次数,取出现次数最大的,替换次数最少,为n - cnt[i]
阅读更多

基础05-Navigation

简介

NavController是中央导航 API。它会跟踪用户访问过的目的地,并允许用户在目的地之间移动。

获取NavController

  • fragment

如果是NavHostFragment

1
val navController = this.navController
阅读更多

基础04-LiveData

LiveData

LiveData的观察者

1
2
3
4
5
6
7
fun interface Observer<T> {

/**
* Called when the data is changed to [value].
*/
fun onChanged(value: T)
}
  • 通过onChanged函数分派数据变化

成员

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
@SuppressWarnings("WeakerAccess") /* synthetic access */
final Object mDataLock = new Object();
static final int START_VERSION = -1;
@SuppressWarnings("WeakerAccess") /* synthetic access */
static final Object NOT_SET = new Object();

private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
new SafeIterableMap<>();

// how many observers are in active state
@SuppressWarnings("WeakerAccess") /* synthetic access */
int mActiveCount = 0;
// to handle active/inactive reentry, we guard with this boolean
private boolean mChangingActiveState;
private volatile Object mData; // 1️⃣:当前的data
// when setData is called, we set the pending data and actual data swap happens on the main
// thread
@SuppressWarnings("WeakerAccess") /* synthetic access */
volatile Object mPendingData = NOT_SET; // 2️⃣:给多线程使用的,在4️⃣mPostValueRunnable中使用
private int mVersion; // 3️⃣:mVersion是数据版本

private boolean mDispatchingValue;
@SuppressWarnings("FieldCanBeLocal")
private boolean mDispatchInvalidated;
private final Runnable mPostValueRunnable = new Runnable() {// 4️⃣mPostValueRunnable,在主线程中将mPendingData设置为当前值
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
阅读更多

基础02-viewModel

ViewModel简介

在了解ViewModel之前,我们先来了解一下MVC, MVP, MVVM的发展Difference Between MVC, MVP and MVVM Architecture Pattern in Android

ViewModelStoreOwner

1
2
3
4
5
6
7
interface ViewModelStoreOwner {

/**
* The owned [ViewModelStore]
*/
val viewModelStore: ViewModelStore
}

ViewModelStore

阅读更多

基础03-Lifecycle

lifeCycle的Observer

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
public interface LifecycleObserver

public interface DefaultLifecycleObserver : LifecycleObserver {
/**
* Notifies that `ON_CREATE` event occurred.
*
*
* This method will be called after the [LifecycleOwner]'s `onCreate`
* method returns.
*
* @param owner the component, whose state was changed
*/
public fun onCreate(owner: LifecycleOwner) {}

/**
* Notifies that `ON_START` event occurred.
*
*
* This method will be called after the [LifecycleOwner]'s `onStart` method returns.
*
* @param owner the component, whose state was changed
*/
public fun onStart(owner: LifecycleOwner) {}

/**
* Notifies that `ON_RESUME` event occurred.
*
*
* This method will be called after the [LifecycleOwner]'s `onResume`
* method returns.
*
* @param owner the component, whose state was changed
*/
public fun onResume(owner: LifecycleOwner) {}

/**
* Notifies that `ON_PAUSE` event occurred.
*
*
* This method will be called before the [LifecycleOwner]'s `onPause` method
* is called.
*
* @param owner the component, whose state was changed
*/
public fun onPause(owner: LifecycleOwner) {}

/**
* Notifies that `ON_STOP` event occurred.
*
*
* This method will be called before the [LifecycleOwner]'s `onStop` method
* is called.
*
* @param owner the component, whose state was changed
*/
public fun onStop(owner: LifecycleOwner) {}

/**
* Notifies that `ON_DESTROY` event occurred.
*
*
* This method will be called before the [LifecycleOwner]'s `onDestroy` method
* is called.
*
* @param owner the component, whose state was changed
*/
public fun onDestroy(owner: LifecycleOwner) {}
}

public fun interface LifecycleEventObserver : LifecycleObserver {
/**
* Called when a state transition event happens.
*
* @param source The source of the event
* @param event The event
*/
public fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event)
}
  • 可以看到,我们在使用lifecycle.addObserver()时,可以传入LifecycleEventObserver或DefaultLifecycleObserver,一个通过event获取当前状态,一个通过不同的回调函数获取当前状态

Activity树

1
2
3
4
5
6
7
8
9
10
11
Activity -- AccountAuthenticatorActivity
|- ActivityGroup -- TabActivity
|- ExpandableListActivity
|- LauncherActivity
|- ListActivity -- PreferenceActivity
|- NativeActivity
|- androidx.core.app.ComponentActivity -- androidx.activity.ComponentActivity -- FragmentActivity -- AppCompatActivity
|- PreviewActivity
|- BootstrapActivity
|- EmptyActivity
|- EmptyFloatingActivity

LifecycleOwner

阅读更多

MIUISupermarket移植

VerifyError

1
java.lang.VerifyError: Verifier rejected class com.xiaomi.market.util.UIUtils: void com.xiaomi.market.util.UIUtils.setStatusBarDarkMode(android.app.Activity, boolean) failed to verify: void com.xiaomi.market.util.UIUtils.setStatusBarDarkMode(android.app.Activity, boolean): [0x15] type Undefined unexpected as arg to if-eqz/if-nez (declaration of 'com.xiaomi.market.util.UIUtils' appears in /data/app/~~pH0reBrzyfvMag1T-TAoDw==/com.xiaomi.market-EzZXS_MznmhQs5NCCbvqfA==/base.apk!classes2.dex)
  • 一般出现VerifyError都是因为对smali代码修改,导致无法通过验证。当前遇到过的情况有:
    • 插入代码时无意覆盖了下面会用到的寄存器的值,导致寄存器类型不匹配等问题。
    • 对方法参数类型修改但未修改调用时传入的参数
    • 传递参数时传递了类型不匹配的参数

ClassNotFound

在xiaomi商店中使用了Lmiui/os/Build类,该类继承Landroid/os/Build,且存在于小米系统中,导致类找不到。导致运行时闪退。

对于这类小米系统中才能获取到的类,采用等价替换的方法进行修复。如在Lmiui/os/Build中有:

阅读更多

基础01-Context

大纲

  • Context类
    • 注解
      • 用于标注文件、SharedPreferences、数据库的打开方式的注解
      • 用于标注bindService时,service的flags的注解
      • 用于标注registerReceiver时,receiver的flags的注解
      • 用于标注getService时,servicesName的注解
      • 用于标注createPackageContext、createPackageContextAsUser、createContextAsUser、createApplicationContext时的flags的注解
    • 常量定义
      • 对应上面注解中限制的常量
      • WAL

Context类

Context是抽象类,具体实现在ContextImpl,Application,Service,Activity都直接或间接继承自ContextWrapper,ContextWrapper通过代理的方式调用真正的ContextImpl。

注解

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
/** @hide */
@IntDef(flag = true, prefix = { "MODE_" }, value = {
MODE_PRIVATE,
MODE_WORLD_READABLE,
MODE_WORLD_WRITEABLE,
MODE_APPEND,
})
@Retention(RetentionPolicy.SOURCE)
public @interface FileMode {}

/** @hide */
@IntDef(flag = true, prefix = { "MODE_" }, value = {
MODE_PRIVATE,
MODE_WORLD_READABLE,
MODE_WORLD_WRITEABLE,
MODE_MULTI_PROCESS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface PreferencesMode {}

/** @hide */
@IntDef(flag = true, prefix = { "MODE_" }, value = {
MODE_PRIVATE,
MODE_WORLD_READABLE,
MODE_WORLD_WRITEABLE,
MODE_ENABLE_WRITE_AHEAD_LOGGING,
MODE_NO_LOCALIZED_COLLATORS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface DatabaseMode {}
阅读更多

01-layout

ID

创建 RelativeLayout 时,请务必为视图对象定义 ID。在相对布局中,同级视图可以定义其相对于通过唯一 ID 引用的另一个同级视图的布局。

findViewById

ID 不必在整个树状结构中具有唯一性,但在您搜索的树状结构部分中必须是唯一的。它通常可能是整个树,因此最好尽可能使其具有唯一性。

  • findViewById是View的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Finds the first descendant view with the given ID, the view itself if
* the ID matches {@link #getId()}, or {@code null} if the ID is invalid
* (< 0) or there is no matching view in the hierarchy.
* <p>
* <strong>Note:</strong> In most cases -- depending on compiler support --
* the resulting view is automatically cast to the target class type. If
* the target class type is unconstrained, an explicit cast may be
* necessary.
*
* @param id the ID to search for
* @return a view with given ID if found, or {@code null} otherwise
* @see View#requireViewById(int)
*/
@Nullable
public final <T extends View> T findViewById(@IdRes int id) {
if (id == NO_ID) {
return null;
}
return findViewTraversal(id);
}
阅读更多

git的使用

版本控制发展历史

本地代码版本控制

RCS: 只能保存本地的变化情况,无法协同合作

集中式版本控制

SVN: 远端服务器维护版本,本地不保存代码版本

分布式版本控制

阅读更多