consumer) {
26 | reference = new WeakReference(target);
27 | this.consumer = consumer;
28 | }
29 |
30 | public void execute() {
31 | if (action != null && isLive()) {
32 | action.call();
33 | }
34 | }
35 |
36 | public void execute(T parameter) {
37 | if (consumer != null
38 | && isLive()) {
39 | consumer.call(parameter);
40 | }
41 | }
42 |
43 | public void markForDeletion() {
44 | reference.clear();
45 | reference = null;
46 | action = null;
47 | consumer = null;
48 | }
49 |
50 | public BindingAction getBindingAction() {
51 | return action;
52 | }
53 |
54 | public BindingConsumer getBindingConsumer() {
55 | return consumer;
56 | }
57 |
58 | public boolean isLive() {
59 | if (reference == null) {
60 | return false;
61 | }
62 | if (reference.get() == null) {
63 | return false;
64 | }
65 | return true;
66 | }
67 |
68 |
69 | public Object getTarget() {
70 | if (reference != null) {
71 | return reference.get();
72 | }
73 | return null;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/bus/event/SingleLiveEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package me.goldze.mvvmhabit.bus.event;
18 |
19 | import android.util.Log;
20 |
21 | import java.util.concurrent.atomic.AtomicBoolean;
22 |
23 | import androidx.annotation.MainThread;
24 | import androidx.annotation.NonNull;
25 | import androidx.annotation.Nullable;
26 | import androidx.lifecycle.LifecycleOwner;
27 | import androidx.lifecycle.MutableLiveData;
28 | import androidx.lifecycle.Observer;
29 |
30 | /**
31 | * A lifecycle-aware observable that sends only new updates after subscription, used for events like
32 | * navigation and Snackbar messages.
33 | *
34 | * This avoids a common problem with events: on configuration change (like rotation) an update
35 | * can be emitted if the observer is active. This LiveData only calls the observable if there's an
36 | * explicit call to setValue() or call().
37 | *
38 | * Note that only one observer is going to be notified of changes.
39 | */
40 | public class SingleLiveEvent extends MutableLiveData {
41 | private static final String TAG = "SingleLiveEvent";
42 |
43 | private final AtomicBoolean mPending = new AtomicBoolean(false);
44 |
45 | @MainThread
46 | public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer super T> observer) {
47 |
48 | if (hasActiveObservers()) {
49 | Log.w(TAG, "Multiple observers registered but only one will be notified of changes.");
50 | }
51 |
52 | // Observe the internal MutableLiveData
53 | super.observe(owner, new Observer() {
54 | @Override
55 | public void onChanged(@Nullable T t) {
56 | if (mPending.compareAndSet(true, false)) {
57 | observer.onChanged(t);
58 | }
59 | }
60 | });
61 | }
62 |
63 | @MainThread
64 | public void setValue(@Nullable T t) {
65 | mPending.set(true);
66 | super.setValue(t);
67 | }
68 |
69 | /**
70 | * Used for cases where T is Void, to make calls cleaner.
71 | */
72 | @MainThread
73 | public void call() {
74 | setValue(null);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/bus/event/SnackbarMessage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package me.goldze.mvvmhabit.bus.event;
18 |
19 | import androidx.annotation.Nullable;
20 | import androidx.annotation.StringRes;
21 | import androidx.lifecycle.LifecycleOwner;
22 | import androidx.lifecycle.Observer;
23 |
24 | /**
25 | * A SingleLiveEvent used for Snackbar messages. Like a {@link SingleLiveEvent} but also prevents
26 | * null messages and uses a custom observer.
27 | *
28 | * Note that only one observer is going to be notified of changes.
29 | */
30 | public class SnackbarMessage extends SingleLiveEvent {
31 |
32 | public void observe(LifecycleOwner owner, final SnackbarObserver observer) {
33 | super.observe(owner, new Observer() {
34 | @Override
35 | public void onChanged(@Nullable Integer t) {
36 | if (t == null) {
37 | return;
38 | }
39 | observer.onNewMessage(t);
40 | }
41 | });
42 | }
43 |
44 | public interface SnackbarObserver {
45 | /**
46 | * Called when there is a new message to be shown.
47 | * @param snackbarMessageResourceId The new message, non-null.
48 | */
49 | void onNewMessage(@StringRes int snackbarMessageResourceId);
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/crash/CaocInitProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2017 Eduard Ereza Martínez
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | *
7 | * You may obtain a copy of the License at
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package me.goldze.mvvmhabit.crash;
18 |
19 | import android.content.ContentProvider;
20 | import android.content.ContentValues;
21 | import android.database.Cursor;
22 | import android.net.Uri;
23 |
24 | import androidx.annotation.NonNull;
25 | import androidx.annotation.Nullable;
26 |
27 |
28 | public class CaocInitProvider extends ContentProvider {
29 |
30 | public boolean onCreate() {
31 | CustomActivityOnCrash.install(getContext());
32 | return false;
33 | }
34 |
35 | @Nullable
36 | @Override
37 | public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
38 | return null;
39 | }
40 |
41 | @Nullable
42 | @Override
43 | public String getType(@NonNull Uri uri) {
44 | return null;
45 | }
46 |
47 | @Nullable
48 | @Override
49 | public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
50 | return null;
51 | }
52 |
53 | @Override
54 | public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
55 | return 0;
56 | }
57 |
58 | @Override
59 | public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
60 | return 0;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/BaseResponse.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http;
2 |
3 | /**
4 | * Created by goldze on 2017/5/10.
5 | * 该类仅供参考,实际业务返回的固定字段, 根据需求来定义,
6 | */
7 | public class BaseResponse {
8 | private int code;
9 | private String message;
10 | private T result;
11 |
12 | public int getCode() {
13 | return code;
14 | }
15 |
16 | public void setCode(int code) {
17 | this.code = code;
18 | }
19 |
20 | public T getResult() {
21 | return result;
22 | }
23 |
24 | public void setResult(T result) {
25 | this.result = result;
26 | }
27 |
28 | public boolean isOk() {
29 | return code == 0;
30 | }
31 |
32 | public String getMessage() {
33 | return message;
34 | }
35 |
36 | public void setMessage(String message) {
37 | this.message = message;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/DownLoadManager.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http;
2 |
3 | import java.util.concurrent.TimeUnit;
4 |
5 | import io.reactivex.Observable;
6 | import io.reactivex.android.schedulers.AndroidSchedulers;
7 | import io.reactivex.functions.Consumer;
8 | import io.reactivex.schedulers.Schedulers;
9 | import me.goldze.mvvmhabit.http.download.DownLoadSubscriber;
10 | import me.goldze.mvvmhabit.http.download.ProgressCallBack;
11 | import me.goldze.mvvmhabit.http.interceptor.ProgressInterceptor;
12 | import okhttp3.OkHttpClient;
13 | import okhttp3.ResponseBody;
14 | import retrofit2.Retrofit;
15 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
16 | import retrofit2.http.GET;
17 | import retrofit2.http.Streaming;
18 | import retrofit2.http.Url;
19 |
20 | /**
21 | * Created by goldze on 2017/5/11.
22 | * 文件下载管理,封装一行代码实现下载
23 | */
24 |
25 | public class DownLoadManager {
26 | private static DownLoadManager instance;
27 |
28 | private static Retrofit retrofit;
29 |
30 | private DownLoadManager() {
31 | buildNetWork();
32 | }
33 |
34 | /**
35 | * 单例模式
36 | *
37 | * @return DownLoadManager
38 | */
39 | public static DownLoadManager getInstance() {
40 | if (instance == null) {
41 | instance = new DownLoadManager();
42 | }
43 | return instance;
44 | }
45 |
46 | //下载
47 | public void load(String downUrl, final ProgressCallBack callBack) {
48 | retrofit.create(ApiService.class)
49 | .download(downUrl)
50 | .subscribeOn(Schedulers.io())//请求网络 在调度者的io线程
51 | .observeOn(Schedulers.io()) //指定线程保存文件
52 | .doOnNext(new Consumer() {
53 | @Override
54 | public void accept(ResponseBody responseBody) throws Exception {
55 | callBack.saveFile(responseBody);
56 | }
57 | })
58 | .observeOn(AndroidSchedulers.mainThread()) //在主线程中更新ui
59 | .subscribe(new DownLoadSubscriber(callBack));
60 | }
61 |
62 | private void buildNetWork() {
63 | OkHttpClient okHttpClient = new OkHttpClient.Builder()
64 | .addInterceptor(new ProgressInterceptor())
65 | .connectTimeout(20, TimeUnit.SECONDS)
66 | .build();
67 |
68 | retrofit = new Retrofit.Builder()
69 | .client(okHttpClient)
70 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
71 | .baseUrl(NetworkUtil.url)
72 | .build();
73 | }
74 |
75 | private interface ApiService {
76 | @Streaming
77 | @GET
78 | Observable download(@Url String url);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/ResponseThrowable.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http;
2 |
3 | /**
4 | * Created by goldze on 2017/5/11.
5 | */
6 |
7 | public class ResponseThrowable extends Exception {
8 | public int code;
9 | public String message;
10 |
11 | public ResponseThrowable(Throwable throwable, int code) {
12 | super(throwable);
13 | this.code = code;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/cookie/CookieJarImpl.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.cookie;
2 |
3 |
4 | import java.util.List;
5 |
6 | import me.goldze.mvvmhabit.http.cookie.store.CookieStore;
7 | import okhttp3.Cookie;
8 | import okhttp3.CookieJar;
9 | import okhttp3.HttpUrl;
10 |
11 | /**
12 | * Created by goldze on 2017/5/13.
13 | */
14 | public class CookieJarImpl implements CookieJar {
15 |
16 | private CookieStore cookieStore;
17 |
18 | public CookieJarImpl(CookieStore cookieStore) {
19 | if (cookieStore == null) {
20 | throw new IllegalArgumentException("cookieStore can not be null!");
21 | }
22 | this.cookieStore = cookieStore;
23 | }
24 |
25 | @Override
26 | public synchronized void saveFromResponse(HttpUrl url, List cookies) {
27 | cookieStore.saveCookie(url, cookies);
28 | }
29 |
30 | @Override
31 | public synchronized List loadForRequest(HttpUrl url) {
32 | return cookieStore.loadCookie(url);
33 | }
34 |
35 | public CookieStore getCookieStore() {
36 | return cookieStore;
37 | }
38 | }
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/cookie/store/CookieStore.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.cookie.store;
2 |
3 | import java.util.List;
4 |
5 | import okhttp3.Cookie;
6 | import okhttp3.HttpUrl;
7 |
8 | /**
9 | * Created by goldze on 2017/5/13.
10 | */
11 | public interface CookieStore {
12 |
13 | /** 保存url对应所有cookie */
14 | void saveCookie(HttpUrl url, List cookie);
15 |
16 | /** 保存url对应所有cookie */
17 | void saveCookie(HttpUrl url, Cookie cookie);
18 |
19 | /** 加载url所有的cookie */
20 | List loadCookie(HttpUrl url);
21 |
22 | /** 获取当前所有保存的cookie */
23 | List getAllCookie();
24 |
25 | /** 获取当前url对应的所有的cookie */
26 | List getCookie(HttpUrl url);
27 |
28 | /** 根据url和cookie移除对应的cookie */
29 | boolean removeCookie(HttpUrl url, Cookie cookie);
30 |
31 | /** 根据url移除所有的cookie */
32 | boolean removeCookie(HttpUrl url);
33 |
34 | /** 移除所有的cookie */
35 | boolean removeAllCookie();
36 | }
37 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/cookie/store/MemoryCookieStore.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.cookie.store;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Set;
7 |
8 | import okhttp3.Cookie;
9 | import okhttp3.HttpUrl;
10 |
11 | /**
12 | * Created by goldze on 2017/5/13.
13 | */
14 | public class MemoryCookieStore implements CookieStore {
15 |
16 | private final HashMap> memoryCookies = new HashMap<>();
17 |
18 | @Override
19 | public synchronized void saveCookie(HttpUrl url, List cookies) {
20 | List oldCookies = memoryCookies.get(url.host());
21 | List needRemove = new ArrayList<>();
22 | for (Cookie newCookie : cookies) {
23 | for (Cookie oldCookie : oldCookies) {
24 | if (newCookie.name().equals(oldCookie.name())) {
25 | needRemove.add(oldCookie);
26 | }
27 | }
28 | }
29 | oldCookies.removeAll(needRemove);
30 | oldCookies.addAll(cookies);
31 | }
32 |
33 | @Override
34 | public synchronized void saveCookie(HttpUrl url, Cookie cookie) {
35 | List cookies = memoryCookies.get(url.host());
36 | List needRemove = new ArrayList<>();
37 | for (Cookie item : cookies) {
38 | if (cookie.name().equals(item.name())) {
39 | needRemove.add(item);
40 | }
41 | }
42 | cookies.removeAll(needRemove);
43 | cookies.add(cookie);
44 | }
45 |
46 | @Override
47 | public synchronized List loadCookie(HttpUrl url) {
48 | List cookies = memoryCookies.get(url.host());
49 | if (cookies == null) {
50 | cookies = new ArrayList<>();
51 | memoryCookies.put(url.host(), cookies);
52 | }
53 | return cookies;
54 | }
55 |
56 | @Override
57 | public synchronized List getAllCookie() {
58 | List cookies = new ArrayList<>();
59 | Set httpUrls = memoryCookies.keySet();
60 | for (String url : httpUrls) {
61 | cookies.addAll(memoryCookies.get(url));
62 | }
63 | return cookies;
64 | }
65 |
66 | @Override
67 | public List getCookie(HttpUrl url) {
68 | List cookies = new ArrayList<>();
69 | List urlCookies = memoryCookies.get(url.host());
70 | if (urlCookies != null) cookies.addAll(urlCookies);
71 | return cookies;
72 | }
73 |
74 | @Override
75 | public synchronized boolean removeCookie(HttpUrl url, Cookie cookie) {
76 | List cookies = memoryCookies.get(url.host());
77 | return (cookie != null) && cookies.remove(cookie);
78 | }
79 |
80 | @Override
81 | public synchronized boolean removeCookie(HttpUrl url) {
82 | return memoryCookies.remove(url.host()) != null;
83 | }
84 |
85 | @Override
86 | public synchronized boolean removeAllCookie() {
87 | memoryCookies.clear();
88 | return true;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/cookie/store/SerializableHttpCookie.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.cookie.store;
2 |
3 | import java.io.IOException;
4 | import java.io.ObjectInputStream;
5 | import java.io.ObjectOutputStream;
6 | import java.io.Serializable;
7 |
8 | import okhttp3.Cookie;
9 |
10 | public class SerializableHttpCookie implements Serializable {
11 | private static final long serialVersionUID = 6374381323722046732L;
12 |
13 | private transient final Cookie cookie;
14 | private transient Cookie clientCookie;
15 |
16 | public SerializableHttpCookie(Cookie cookie) {
17 | this.cookie = cookie;
18 | }
19 |
20 | public Cookie getCookie() {
21 | Cookie bestCookie = cookie;
22 | if (clientCookie != null) {
23 | bestCookie = clientCookie;
24 | }
25 | return bestCookie;
26 | }
27 |
28 | private void writeObject(ObjectOutputStream out) throws IOException {
29 | out.writeObject(cookie.name());
30 | out.writeObject(cookie.value());
31 | out.writeLong(cookie.expiresAt());
32 | out.writeObject(cookie.domain());
33 | out.writeObject(cookie.path());
34 | out.writeBoolean(cookie.secure());
35 | out.writeBoolean(cookie.httpOnly());
36 | out.writeBoolean(cookie.hostOnly());
37 | out.writeBoolean(cookie.persistent());
38 | }
39 |
40 | private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
41 | String name = (String) in.readObject();
42 | String value = (String) in.readObject();
43 | long expiresAt = in.readLong();
44 | String domain = (String) in.readObject();
45 | String path = (String) in.readObject();
46 | boolean secure = in.readBoolean();
47 | boolean httpOnly = in.readBoolean();
48 | boolean hostOnly = in.readBoolean();
49 | boolean persistent = in.readBoolean();
50 | Cookie.Builder builder = new Cookie.Builder();
51 | builder = builder.name(name);
52 | builder = builder.value(value);
53 | builder = builder.expiresAt(expiresAt);
54 | builder = hostOnly ? builder.hostOnlyDomain(domain) : builder.domain(domain);
55 | builder = builder.path(path);
56 | builder = secure ? builder.secure() : builder;
57 | builder = httpOnly ? builder.httpOnly() : builder;
58 | clientCookie = builder.build();
59 | }
60 | }
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/download/DownLoadStateBean.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.download;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * Created by goldze on 2017/5/11.
10 | */
11 |
12 | public class DownLoadStateBean implements Serializable, Parcelable {
13 | long total; // 文件总大小
14 | long bytesLoaded; //已加载文件的大小
15 | String tag; // 多任务下载时的一个标记
16 |
17 | public DownLoadStateBean(long total, long bytesLoaded) {
18 | this.total = total;
19 | this.bytesLoaded = bytesLoaded;
20 | }
21 |
22 | public DownLoadStateBean(long total, long bytesLoaded, String tag) {
23 | this.total = total;
24 | this.bytesLoaded = bytesLoaded;
25 | this.tag = tag;
26 | }
27 |
28 | public long getTotal() {
29 | return total;
30 | }
31 |
32 | public void setTotal(long total) {
33 | this.total = total;
34 | }
35 |
36 | public long getBytesLoaded() {
37 | return bytesLoaded;
38 | }
39 |
40 | public void setBytesLoaded(long bytesLoaded) {
41 | this.bytesLoaded = bytesLoaded;
42 | }
43 |
44 | public String getTag() {
45 | return tag;
46 | }
47 |
48 | public void setTag(String tag) {
49 | this.tag = tag;
50 | }
51 |
52 | @Override
53 | public int describeContents() {
54 | return 0;
55 | }
56 |
57 | @Override
58 | public void writeToParcel(Parcel dest, int flags) {
59 | dest.writeLong(this.total);
60 | dest.writeLong(this.bytesLoaded);
61 | dest.writeString(this.tag);
62 | }
63 |
64 | protected DownLoadStateBean(Parcel in) {
65 | this.total = in.readLong();
66 | this.bytesLoaded = in.readLong();
67 | this.tag = in.readString();
68 | }
69 |
70 | public static final Creator CREATOR = new Creator() {
71 | @Override
72 | public DownLoadStateBean createFromParcel(Parcel source) {
73 | return new DownLoadStateBean(source);
74 | }
75 |
76 | @Override
77 | public DownLoadStateBean[] newArray(int size) {
78 | return new DownLoadStateBean[size];
79 | }
80 | };
81 | }
82 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/download/DownLoadSubscriber.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.download;
2 |
3 | import io.reactivex.observers.DisposableObserver;
4 |
5 | /**
6 | * Created by goldze on 2017/5/11.
7 | */
8 |
9 | public class DownLoadSubscriber extends DisposableObserver {
10 | private ProgressCallBack fileCallBack;
11 |
12 | public DownLoadSubscriber(ProgressCallBack fileCallBack) {
13 | this.fileCallBack = fileCallBack;
14 | }
15 |
16 | @Override
17 | public void onStart() {
18 | super.onStart();
19 | if (fileCallBack != null)
20 | fileCallBack.onStart();
21 | }
22 |
23 | @Override
24 | public void onComplete() {
25 | if (fileCallBack != null)
26 | fileCallBack.onCompleted();
27 | }
28 |
29 | @Override
30 | public void onError(Throwable e) {
31 | if (fileCallBack != null)
32 | fileCallBack.onError(e);
33 | }
34 |
35 | @Override
36 | public void onNext(T t) {
37 | if (fileCallBack != null)
38 | fileCallBack.onSuccess(t);
39 | }
40 | }
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/download/ProgressCallBack.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.download;
2 |
3 | import android.util.Log;
4 |
5 | import java.io.File;
6 | import java.io.FileNotFoundException;
7 | import java.io.FileOutputStream;
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 |
11 | import io.reactivex.android.schedulers.AndroidSchedulers;
12 | import io.reactivex.disposables.Disposable;
13 | import io.reactivex.functions.Consumer;
14 | import me.goldze.mvvmhabit.bus.RxBus;
15 | import me.goldze.mvvmhabit.bus.RxSubscriptions;
16 | import okhttp3.ResponseBody;
17 |
18 | /**
19 | * Created by goldze on 2017/9/26 0026.
20 | */
21 |
22 | public abstract class ProgressCallBack {
23 |
24 | private String destFileDir; // 本地文件存放路径
25 | private String destFileName; // 文件名
26 | private Disposable mSubscription;
27 |
28 | public ProgressCallBack(String destFileDir, String destFileName) {
29 | this.destFileDir = destFileDir;
30 | this.destFileName = destFileName;
31 | subscribeLoadProgress();
32 | }
33 |
34 | public abstract void onSuccess(T t);
35 |
36 | public abstract void progress(long progress, long total);
37 |
38 | public void onStart() {
39 | }
40 |
41 | public void onCompleted() {
42 | }
43 |
44 | public abstract void onError(Throwable e);
45 |
46 | public void saveFile(ResponseBody body) {
47 | InputStream is = null;
48 | byte[] buf = new byte[2048];
49 | int len;
50 | FileOutputStream fos = null;
51 | try {
52 | is = body.byteStream();
53 | File dir = new File(destFileDir);
54 | if (!dir.exists()) {
55 | dir.mkdirs();
56 | }
57 | File file = new File(dir, destFileName);
58 | fos = new FileOutputStream(file);
59 | while ((len = is.read(buf)) != -1) {
60 | fos.write(buf, 0, len);
61 | }
62 | fos.flush();
63 | //onCompleted();
64 | } catch (FileNotFoundException e) {
65 | e.printStackTrace();
66 | } catch (IOException e) {
67 | e.printStackTrace();
68 | } finally {
69 | try {
70 | if (is != null) is.close();
71 | if (fos != null) fos.close();
72 | unsubscribe();
73 | } catch (IOException e) {
74 | Log.e("saveFile", e.getMessage());
75 | }
76 | }
77 | }
78 |
79 | /**
80 | * 订阅加载的进度条
81 | */
82 | public void subscribeLoadProgress() {
83 | mSubscription = RxBus.getDefault().toObservable(DownLoadStateBean.class)
84 | .observeOn(AndroidSchedulers.mainThread()) //回调到主线程更新UI
85 | .subscribe(new Consumer() {
86 | @Override
87 | public void accept(final DownLoadStateBean progressLoadBean) throws Exception {
88 | progress(progressLoadBean.getBytesLoaded(), progressLoadBean.getTotal());
89 | }
90 | });
91 | //将订阅者加入管理站
92 | RxSubscriptions.add(mSubscription);
93 | }
94 |
95 | /**
96 | * 取消订阅,防止内存泄漏
97 | */
98 | public void unsubscribe() {
99 | RxSubscriptions.remove(mSubscription);
100 | }
101 | }
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/download/ProgressResponseBody.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.download;
2 |
3 | import java.io.IOException;
4 |
5 | import me.goldze.mvvmhabit.bus.RxBus;
6 | import okhttp3.MediaType;
7 | import okhttp3.ResponseBody;
8 | import okio.Buffer;
9 | import okio.BufferedSource;
10 | import okio.ForwardingSource;
11 | import okio.Okio;
12 | import okio.Source;
13 |
14 | /**
15 | * Created by goldze on 2017/5/11.
16 | */
17 |
18 | public class ProgressResponseBody extends ResponseBody {
19 | private ResponseBody responseBody;
20 |
21 | private BufferedSource bufferedSource;
22 | private String tag;
23 |
24 | public ProgressResponseBody(ResponseBody responseBody) {
25 | this.responseBody = responseBody;
26 | }
27 |
28 | public ProgressResponseBody(ResponseBody responseBody, String tag) {
29 | this.responseBody = responseBody;
30 | this.tag = tag;
31 | }
32 |
33 | @Override
34 | public MediaType contentType() {
35 | return responseBody.contentType();
36 | }
37 |
38 | @Override
39 | public long contentLength() {
40 | return responseBody.contentLength();
41 | }
42 |
43 | @Override
44 | public BufferedSource source() {
45 | if (bufferedSource == null) {
46 | bufferedSource = Okio.buffer(source(responseBody.source()));
47 | }
48 | return bufferedSource;
49 | }
50 |
51 | private Source source(Source source) {
52 | return new ForwardingSource(source) {
53 | long bytesReaded = 0;
54 |
55 | @Override
56 | public long read(Buffer sink, long byteCount) throws IOException {
57 | long bytesRead = super.read(sink, byteCount);
58 | bytesReaded += bytesRead == -1 ? 0 : bytesRead;
59 | //使用RxBus的方式,实时发送当前已读取(上传/下载)的字节数据
60 | RxBus.getDefault().post(new DownLoadStateBean(contentLength(), bytesReaded, tag));
61 | return bytesRead;
62 | }
63 | };
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/interceptor/BaseInterceptor.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.interceptor;
2 |
3 | import java.io.IOException;
4 | import java.util.Map;
5 | import java.util.Set;
6 |
7 | import okhttp3.Interceptor;
8 | import okhttp3.Request;
9 | import okhttp3.Response;
10 |
11 | /**
12 | * Created by goldze on 2017/5/10.
13 | */
14 | public class BaseInterceptor implements Interceptor {
15 | private Map headers;
16 |
17 | public BaseInterceptor(Map headers) {
18 | this.headers = headers;
19 | }
20 |
21 | @Override
22 | public Response intercept(Chain chain) throws IOException {
23 | Request.Builder builder = chain.request()
24 | .newBuilder();
25 | if (headers != null && headers.size() > 0) {
26 | Set keys = headers.keySet();
27 | for (String headerKey : keys) {
28 | builder.addHeader(headerKey, headers.get(headerKey)).build();
29 | }
30 | }
31 | //请求信息
32 | return chain.proceed(builder.build());
33 | }
34 | }
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/interceptor/CacheInterceptor.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.interceptor;
2 |
3 | import android.content.Context;
4 |
5 | import java.io.IOException;
6 |
7 | import me.goldze.mvvmhabit.http.NetworkUtil;
8 | import okhttp3.CacheControl;
9 | import okhttp3.Interceptor;
10 | import okhttp3.Request;
11 | import okhttp3.Response;
12 |
13 | /**
14 | * Created by goldze on 2017/5/10.
15 | * 无网络状态下智能读取缓存的拦截器
16 | */
17 | public class CacheInterceptor implements Interceptor {
18 |
19 | private Context context;
20 |
21 | public CacheInterceptor(Context context) {
22 | this.context = context;
23 | }
24 |
25 | @Override
26 | public Response intercept(Chain chain) throws IOException {
27 | Request request = chain.request();
28 | if (NetworkUtil.isNetworkAvailable(context)) {
29 | Response response = chain.proceed(request);
30 | // read from cache for 60 s
31 | int maxAge = 60;
32 | return response.newBuilder()
33 | .removeHeader("Pragma")
34 | .removeHeader("Cache-Control")
35 | .header("Cache-Control", "public, max-age=" + maxAge)
36 | .build();
37 | } else {
38 | //读取缓存信息
39 | request = request.newBuilder()
40 | .cacheControl(CacheControl.FORCE_CACHE)
41 | .build();
42 | Response response = chain.proceed(request);
43 | //set cache times is 3 days
44 | int maxStale = 60 * 60 * 24 * 3;
45 | return response.newBuilder()
46 | .removeHeader("Pragma")
47 | .removeHeader("Cache-Control")
48 | .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
49 | .build();
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/interceptor/ProgressInterceptor.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.interceptor;
2 |
3 | import java.io.IOException;
4 |
5 | import me.goldze.mvvmhabit.http.download.ProgressResponseBody;
6 | import okhttp3.Interceptor;
7 | import okhttp3.Response;
8 |
9 | /**
10 | * Created by goldze on 2017/5/10.
11 | */
12 |
13 | public class ProgressInterceptor implements Interceptor {
14 |
15 | @Override
16 | public Response intercept(Chain chain) throws IOException {
17 | Response originalResponse = chain.proceed(chain.request());
18 | return originalResponse.newBuilder()
19 | .body(new ProgressResponseBody(originalResponse.body()))
20 | .build();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/interceptor/logging/I.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.interceptor.logging;
2 |
3 |
4 | import java.util.logging.Level;
5 |
6 | import okhttp3.internal.platform.Platform;
7 |
8 | /**
9 | * @author ihsan on 10/02/2017.
10 | */
11 | class I {
12 |
13 | protected I() {
14 | throw new UnsupportedOperationException();
15 | }
16 |
17 | static void log(int type, String tag, String msg) {
18 | java.util.logging.Logger logger = java.util.logging.Logger.getLogger(tag);
19 | switch (type) {
20 | case Platform.INFO:
21 | logger.log(Level.INFO, msg);
22 | break;
23 | default:
24 | logger.log(Level.WARNING, msg);
25 | break;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/interceptor/logging/Level.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.interceptor.logging;
2 |
3 | /**
4 | * @author ihsan on 21/02/2017.
5 | */
6 |
7 | public enum Level {
8 | /**
9 | * No logs.
10 | */
11 | NONE,
12 | /**
13 | * Example:
14 | *
{@code
15 | * - URL
16 | * - Method
17 | * - Headers
18 | * - Body
19 | * }
20 | */
21 | BASIC,
22 | /**
23 | * Example:
24 | *
{@code
25 | * - URL
26 | * - Method
27 | * - Headers
28 | * }
29 | */
30 | HEADERS,
31 | /**
32 | * Example:
33 | *
{@code
34 | * - URL
35 | * - Method
36 | * - Body
37 | * }
38 | */
39 | BODY
40 | }
41 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/http/interceptor/logging/Logger.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.http.interceptor.logging;
2 |
3 | import okhttp3.internal.platform.Platform;
4 |
5 | /**
6 | * @author ihsan on 11/07/2017.
7 | */
8 | @SuppressWarnings({"WeakerAccess", "unused"})
9 | public interface Logger {
10 | void log(int level, String tag, String msg);
11 |
12 | Logger DEFAULT = new Logger() {
13 | @Override
14 | public void log(int level, String tag, String message) {
15 | Platform.get().log(level, message, null);
16 | }
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/utils/CloseUtils.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.utils;
2 |
3 | import java.io.Closeable;
4 | import java.io.IOException;
5 |
6 | /**
7 | * Created by goldze on 2017/5/14.
8 | * 关闭相关工具类
9 | */
10 | public final class CloseUtils {
11 |
12 | private CloseUtils() {
13 | throw new UnsupportedOperationException("u can't instantiate me...");
14 | }
15 |
16 | /**
17 | * 关闭IO
18 | *
19 | * @param closeables closeables
20 | */
21 | public static void closeIO(final Closeable... closeables) {
22 | if (closeables == null) return;
23 | for (Closeable closeable : closeables) {
24 | if (closeable != null) {
25 | try {
26 | closeable.close();
27 | } catch (IOException e) {
28 | e.printStackTrace();
29 | }
30 | }
31 | }
32 | }
33 |
34 | /**
35 | * 安静关闭IO
36 | *
37 | * @param closeables closeables
38 | */
39 | public static void closeIOQuietly(final Closeable... closeables) {
40 | if (closeables == null) return;
41 | for (Closeable closeable : closeables) {
42 | if (closeable != null) {
43 | try {
44 | closeable.close();
45 | } catch (IOException ignored) {
46 | }
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/utils/RxUtils.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.utils;
2 |
3 | import android.content.Context;
4 |
5 | import com.trello.rxlifecycle2.LifecycleProvider;
6 | import com.trello.rxlifecycle2.LifecycleTransformer;
7 |
8 | import androidx.fragment.app.Fragment;
9 | import io.reactivex.Observable;
10 | import io.reactivex.ObservableSource;
11 | import io.reactivex.ObservableTransformer;
12 | import io.reactivex.android.schedulers.AndroidSchedulers;
13 | import io.reactivex.annotations.NonNull;
14 | import io.reactivex.functions.Function;
15 | import io.reactivex.schedulers.Schedulers;
16 | import me.goldze.mvvmhabit.http.BaseResponse;
17 | import me.goldze.mvvmhabit.http.ExceptionHandle;
18 |
19 | /**
20 | * Created by goldze on 2017/6/19.
21 | * 有关Rx的工具类
22 | */
23 | public class RxUtils {
24 | /**
25 | * 生命周期绑定
26 | *
27 | * @param lifecycle Activity
28 | */
29 | public static LifecycleTransformer bindToLifecycle(@NonNull Context lifecycle) {
30 | if (lifecycle instanceof LifecycleProvider) {
31 | return ((LifecycleProvider) lifecycle).bindToLifecycle();
32 | } else {
33 | throw new IllegalArgumentException("context not the LifecycleProvider type");
34 | }
35 | }
36 |
37 | /**
38 | * 生命周期绑定
39 | *
40 | * @param lifecycle Fragment
41 | */
42 | public static LifecycleTransformer bindToLifecycle(@NonNull Fragment lifecycle) {
43 | if (lifecycle instanceof LifecycleProvider) {
44 | return ((LifecycleProvider) lifecycle).bindToLifecycle();
45 | } else {
46 | throw new IllegalArgumentException("fragment not the LifecycleProvider type");
47 | }
48 | }
49 |
50 | /**
51 | * 生命周期绑定
52 | *
53 | * @param lifecycle Fragment
54 | */
55 | public static LifecycleTransformer bindToLifecycle(@NonNull LifecycleProvider lifecycle) {
56 | return lifecycle.bindToLifecycle();
57 | }
58 |
59 | /**
60 | * 线程调度器
61 | */
62 | public static ObservableTransformer schedulersTransformer() {
63 | return new ObservableTransformer() {
64 | @Override
65 | public ObservableSource apply(Observable upstream) {
66 | return upstream.subscribeOn(Schedulers.io())
67 | .observeOn(AndroidSchedulers.mainThread());
68 | }
69 | };
70 | }
71 |
72 | public static ObservableTransformer exceptionTransformer() {
73 |
74 | return new ObservableTransformer() {
75 | @Override
76 | public ObservableSource apply(Observable observable) {
77 | return observable
78 | // .map(new HandleFuc()) //这里可以取出BaseResponse中的Result
79 | .onErrorResumeNext(new HttpResponseFunc());
80 | }
81 | };
82 | }
83 |
84 | private static class HttpResponseFunc implements Function> {
85 | @Override
86 | public Observable apply(Throwable t) {
87 | return Observable.error(ExceptionHandle.handleException(t));
88 | }
89 | }
90 |
91 | private static class HandleFuc implements Function, T> {
92 | @Override
93 | public T apply(BaseResponse response) {
94 | if (!response.isOk())
95 | throw new RuntimeException(!"".equals(response.getCode() + "" + response.getMessage()) ? response.getMessage() : "");
96 | return response.getResult();
97 | }
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/utils/Utils.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.utils;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 |
6 | import androidx.annotation.NonNull;
7 |
8 | /**
9 | * Created by goldze on 2017/5/14.
10 | * 常用工具类
11 | */
12 | public final class Utils {
13 |
14 | @SuppressLint("StaticFieldLeak")
15 | private static Context context;
16 |
17 | private Utils() {
18 | throw new UnsupportedOperationException("u can't instantiate me...");
19 | }
20 |
21 | /**
22 | * 初始化工具类
23 | *
24 | * @param context 上下文
25 | */
26 | public static void init(@NonNull final Context context) {
27 | Utils.context = context.getApplicationContext();
28 | }
29 |
30 | /**
31 | * 获取ApplicationContext
32 | *
33 | * @return ApplicationContext
34 | */
35 | public static Context getContext() {
36 | if (context != null) {
37 | return context;
38 | }
39 | throw new NullPointerException("should be initialized in application");
40 | }
41 | }
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/utils/compression/OnCompressListener.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.utils.compression;
2 |
3 | import java.io.File;
4 |
5 | public interface OnCompressListener {
6 |
7 | /**
8 | * Fired when the compression is started, override to handle in your own code
9 | */
10 | void onStart();
11 |
12 | /**
13 | * Fired when a compression returns successfully, override to handle in your own code
14 | */
15 | void onSuccess(File file);
16 |
17 | /**
18 | * Fired when a compression fails to complete, override to handle in your own code
19 | */
20 | void onError(Throwable e);
21 | }
22 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/utils/compression/Preconditions.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.utils.compression;
2 |
3 | import androidx.annotation.Nullable;
4 |
5 | final class Preconditions {
6 |
7 | /**
8 | * Ensures that an object reference passed as a parameter to the calling method is not null.
9 | *
10 | * @param reference an object reference
11 | * @return the non-null reference that was validated
12 | * @throws NullPointerException if {@code reference} is null
13 | */
14 | static T checkNotNull(T reference) {
15 | if (reference == null) {
16 | throw new NullPointerException();
17 | }
18 | return reference;
19 | }
20 |
21 | /**
22 | * Ensures that an object reference passed as a parameter to the calling method is not null.
23 | *
24 | * @param reference an object reference
25 | * @param errorMessage the exception message to use if the check fails; will be converted to a
26 | * string using {@link String#valueOf(Object)}
27 | * @return the non-null reference that was validated
28 | * @throws NullPointerException if {@code reference} is null
29 | */
30 | static T checkNotNull(T reference, @Nullable Object errorMessage) {
31 | if (reference == null) {
32 | throw new NullPointerException(String.valueOf(errorMessage));
33 | }
34 | return reference;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/utils/constant/MemoryConstants.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.utils.constant;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.RetentionPolicy;
5 |
6 | import androidx.annotation.IntDef;
7 |
8 | /**
9 | * Created by goldze on 2017/5/14.
10 | * 存储相关常量
11 | */
12 | public final class MemoryConstants {
13 |
14 | /**
15 | * Byte与Byte的倍数
16 | */
17 | public static final int BYTE = 1;
18 | /**
19 | * KB与Byte的倍数
20 | */
21 | public static final int KB = 1024;
22 | /**
23 | * MB与Byte的倍数
24 | */
25 | public static final int MB = 1048576;
26 | /**
27 | * GB与Byte的倍数
28 | */
29 | public static final int GB = 1073741824;
30 |
31 | @IntDef({BYTE, KB, MB, GB})
32 | @Retention(RetentionPolicy.SOURCE)
33 | public @interface Unit {
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/utils/constant/TimeConstants.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.utils.constant;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.RetentionPolicy;
5 |
6 | import androidx.annotation.IntDef;
7 |
8 | /**
9 | * Created by goldze on 2017/5/14.
10 | * 时间相关常量
11 | */
12 | public final class TimeConstants {
13 |
14 | /**
15 | * 毫秒与毫秒的倍数
16 | */
17 | public static final int MSEC = 1;
18 | /**
19 | * 秒与毫秒的倍数
20 | */
21 | public static final int SEC = 1000;
22 | /**
23 | * 分与毫秒的倍数
24 | */
25 | public static final int MIN = 60000;
26 | /**
27 | * 时与毫秒的倍数
28 | */
29 | public static final int HOUR = 3600000;
30 | /**
31 | * 天与毫秒的倍数
32 | */
33 | public static final int DAY = 86400000;
34 |
35 | @IntDef({MSEC, SEC, MIN, HOUR, DAY})
36 | @Retention(RetentionPolicy.SOURCE)
37 | public @interface Unit {
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/java/me/goldze/mvvmhabit/widget/ControlDistributeLinearLayout.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit.widget;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.util.AttributeSet;
6 | import android.view.MotionEvent;
7 | import android.widget.LinearLayout;
8 |
9 | import me.goldze.mvvmhabit.R;
10 |
11 | /**
12 | * Created by goldze on 2017/3/16.
13 | * 控制事件分发的LinearLayout
14 | */
15 | public class ControlDistributeLinearLayout extends LinearLayout {
16 | //默认是不拦截事件,分发事件给子View
17 | private boolean isDistributeEvent = false;
18 |
19 | public ControlDistributeLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
20 | super(context, attrs, defStyleAttr);
21 | TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ControlDistributeLinearLayout);
22 | isDistributeEvent = typedArray.getBoolean(R.styleable.ControlDistributeLinearLayout_distribute_event, false);
23 | }
24 |
25 | public ControlDistributeLinearLayout(Context context, AttributeSet attrs) {
26 | this(context, attrs, 0);
27 | }
28 |
29 | public ControlDistributeLinearLayout(Context context) {
30 | this(context, null);
31 | }
32 |
33 | /**
34 | * 重写事件分发方法,false 为分发 , true 为父控件自己消耗, 由外面传进来的参数决定
35 | */
36 | @Override
37 | public boolean onInterceptTouchEvent(MotionEvent ev) {
38 | return isDistributeEvent();
39 | }
40 |
41 | public boolean isDistributeEvent() {
42 | return isDistributeEvent;
43 | }
44 |
45 | public void setDistributeEvent(boolean distributeEvent) {
46 | isDistributeEvent = distributeEvent;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/res/drawable-hdpi/customactivityoncrash_error_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goldze/MVVMHabit/ab2bf079815e260501e2f42b10c1b67329b1de26/mvvmhabit/src/main/res/drawable-hdpi/customactivityoncrash_error_image.png
--------------------------------------------------------------------------------
/mvvmhabit/src/main/res/drawable-mdpi/customactivityoncrash_error_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goldze/MVVMHabit/ab2bf079815e260501e2f42b10c1b67329b1de26/mvvmhabit/src/main/res/drawable-mdpi/customactivityoncrash_error_image.png
--------------------------------------------------------------------------------
/mvvmhabit/src/main/res/drawable-xhdpi/customactivityoncrash_error_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goldze/MVVMHabit/ab2bf079815e260501e2f42b10c1b67329b1de26/mvvmhabit/src/main/res/drawable-xhdpi/customactivityoncrash_error_image.png
--------------------------------------------------------------------------------
/mvvmhabit/src/main/res/drawable-xxhdpi/customactivityoncrash_error_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goldze/MVVMHabit/ab2bf079815e260501e2f42b10c1b67329b1de26/mvvmhabit/src/main/res/drawable-xxhdpi/customactivityoncrash_error_image.png
--------------------------------------------------------------------------------
/mvvmhabit/src/main/res/drawable-xxxhdpi/customactivityoncrash_error_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goldze/MVVMHabit/ab2bf079815e260501e2f42b10c1b67329b1de26/mvvmhabit/src/main/res/drawable-xxxhdpi/customactivityoncrash_error_image.png
--------------------------------------------------------------------------------
/mvvmhabit/src/main/res/layout/activity_container.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/res/layout/customactivityoncrash_default_error_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
22 |
23 |
29 |
30 |
38 |
39 |
45 |
46 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 | #000000
5 | #808080
6 | #FFFF00
7 | #008000
8 | #0000FF
9 | #FFA500
10 |
11 |
12 | - #4B03A9F4
13 | - #3303A9F4
14 | - #1903A9F4
15 |
16 |
17 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 | 12sp
8 |
9 |
--------------------------------------------------------------------------------
/mvvmhabit/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | mvvmhabit
3 | 发生意外错误。\n抱歉,给您带来不便。
4 | 重新启动
5 | 关闭程序
6 | 错误日志
7 | 错误详情
8 | 关闭
9 | 复制日志
10 | 复制日志
11 | 错误信息
12 |
13 |
--------------------------------------------------------------------------------
/mvvmhabit/src/test/java/me/goldze/mvvmhabit/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package me.goldze.mvvmhabit;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':mvvmhabit'
2 |
--------------------------------------------------------------------------------