diff --git a/.idea/misc.xml b/.idea/misc.xml index 401d515..297d212 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 1418cfd..6e6d169 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -154,8 +154,9 @@ - + + @@ -166,7 +167,6 @@ - @@ -176,7 +176,7 @@ - + @@ -674,8 +674,9 @@ - + + diff --git a/DesignResCollection_MVP-Dagger2/app/build.gradle b/DesignResCollection_MVP-Dagger2/app/build.gradle new file mode 100644 index 0000000..3f3c0a2 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/build.gradle @@ -0,0 +1,76 @@ +apply plugin: 'com.android.application' +apply plugin: 'com.neenbedankt.android-apt' + +android { + compileSdkVersion rootProject.ext.compileSdkVersion + buildToolsVersion rootProject.ext.buildToolsVersion + + defaultConfig { + applicationId "com.boredream.designrescollection" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 70 + versionName "0.7.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard.cfg' + } + } + + packagingOptions { + exclude 'META-INF/DEPENDENCIES' + exclude 'META-INF/LICENSE' + exclude 'META-INF/NOTICE' + } + + android.applicationVariants.all { variant -> + renameAPK(variant, defaultConfig, "release") + } +} + +def renameAPK(variant, defaultConfig, buildType) { + variant.outputs.each { output -> + def applicationName = 'DesignResCollection' + def formattedDate = new Date().format('yyyyMMdd') + def file = output.packageApplication.outputFile + def fileName = applicationName + "_v" + defaultConfig.versionName + "_" + formattedDate + "_" + buildType + ".apk" + output.packageApplication.outputFile = new File(file.parent, fileName) + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile project(path: ':bdcodehelper') + + // Dependencies for local unit tests + testCompile "junit:junit:$rootProject.ext.junitVersion" + testCompile "org.mockito:mockito-all:$rootProject.ext.mockitoVersion" + testCompile "org.hamcrest:hamcrest-all:$rootProject.ext.hamcrestVersion" + + // Espresso UI Testing + androidTestCompile "com.android.support.test:runner:$rootProject.runnerVersion" + androidTestCompile "com.android.support.test:rules:$rootProject.rulesVersion" + androidTestCompile "com.android.support.test.espresso:espresso-core:$rootProject.espressoVersion" + androidTestCompile "com.android.support.test.espresso:espresso-contrib:$rootProject.espressoVersion" + androidTestCompile "com.android.support.test.espresso:espresso-intents:$rootProject.espressoVersion" + + // Resolve conflicts between main and test APK: + androidTestCompile "com.android.support:support-annotations:$rootProject.supportLibraryVersion" + androidTestCompile "com.android.support:support-v4:$rootProject.supportLibraryVersion" + androidTestCompile "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion" + + // Dagger dependencies + apt "com.google.dagger:dagger-compiler:$rootProject.daggerVersion" + compile "com.google.dagger:dagger:$rootProject.daggerVersion" + provided 'javax.annotation:javax.annotation-api:1.2' + +} + +configurations { + androidTestCompile.exclude group: 'com.android.support', module: 'support-v4' +} diff --git a/DesignResCollection_MVP-Dagger2/app/proguard.cfg b/DesignResCollection_MVP-Dagger2/app/proguard.cfg new file mode 100644 index 0000000..ee95107 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/proguard.cfg @@ -0,0 +1,80 @@ +######################## 固定部分 ######################## + +#1.基本指令区 +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontskipnonpubliclibraryclassmembers +-dontpreverify +-verbose +-ignorewarning +-printmapping proguardMapping.txt +-optimizations !code/simplification/cast,!field/*,!class/merging/* +-keepattributes *Annotation*,InnerClasses +-keepattributes Signature +-keepattributes SourceFile,LineNumberTable + +#2.默认保留区 +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class * extends android.view.View +-keep public class com.android.vending.licensing.ILicensingService +-keep class android.support.** {*;} + +-keepclasseswithmembernames class * { + native ; +} +-keepclassmembers class * extends android.app.Activity{ + public void *(android.view.View); +} +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} +-keep public class * extends android.view.View{ + *** get*(); + void set*(***); + public (android.content.Context); + public (android.content.Context, android.util.AttributeSet); + public (android.content.Context, android.util.AttributeSet, int); +} +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet); + public (android.content.Context, android.util.AttributeSet, int); +} +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} +-keepclassmembers class * implements java.io.Serializable { + static final long serialVersionUID; + private static final java.io.ObjectStreamField[] serialPersistentFields; + private void writeObject(java.io.ObjectOutputStream); + private void readObject(java.io.ObjectInputStream); + java.lang.Object writeReplace(); + java.lang.Object readResolve(); +} +-keep class **.R$* { + *; +} +-keepclassmembers class * { + void *(**On*Event); +} + +#3.webview +-keepclassmembers class fqcn.of.javascript.interface.for.webview { + public *; +} +-keepclassmembers class * extends android.webkit.webViewClient { + public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap); + public boolean *(android.webkit.WebView, java.lang.String); +} +-keepclassmembers class * extends android.webkit.webViewClient { + public void *(android.webkit.webView, jav.lang.String); +} + +######################## 非固定部分 ######################## diff --git a/DesignResCollection_MVP-Dagger2/app/src/androidTest/java/com/boredream/designrescollection/ApplicationTest.java b/DesignResCollection_MVP-Dagger2/app/src/androidTest/java/com/boredream/designrescollection/ApplicationTest.java new file mode 100644 index 0000000..2ddb8da --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/androidTest/java/com/boredream/designrescollection/ApplicationTest.java @@ -0,0 +1,14 @@ +package com.boredream.designrescollection; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } + +} \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/androidTest/java/com/boredream/designrescollection/idlingres/RxIdlingResource.java b/DesignResCollection_MVP-Dagger2/app/src/androidTest/java/com/boredream/designrescollection/idlingres/RxIdlingResource.java new file mode 100644 index 0000000..96d7a7f --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/androidTest/java/com/boredream/designrescollection/idlingres/RxIdlingResource.java @@ -0,0 +1,99 @@ +package com.boredream.designrescollection.idlingres; + +import android.support.test.espresso.Espresso; +import android.support.test.espresso.IdlingResource; +import android.util.Log; + +import java.util.concurrent.atomic.AtomicInteger; + +import rx.Observable; +import rx.Subscriber; +import rx.plugins.RxJavaObservableExecutionHook; + +public class RxIdlingResource extends RxJavaObservableExecutionHook implements IdlingResource { + + private static final String TAG = "RxIdlingResource"; + + private final AtomicInteger subscriptions = new AtomicInteger(0); + + private static RxIdlingResource INSTANCE; + + private ResourceCallback resourceCallback; + + private RxIdlingResource() { + //private + } + + public static RxIdlingResource get() { + if (INSTANCE == null) { + INSTANCE = new RxIdlingResource(); + Espresso.registerIdlingResources(INSTANCE); + } + return INSTANCE; + } + + /* ======================== */ + /* IdlingResource Overrides */ + /* ======================== */ + + @Override + public String getName() { + return TAG; + } + + @Override + public boolean isIdleNow() { + int activeSubscriptionCount = subscriptions.get(); + return activeSubscriptionCount == 0; + } + + @Override + public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { + this.resourceCallback = resourceCallback; + } + + /* ======================================= */ + /* RxJavaObservableExecutionHook Overrides */ + /* ======================================= */ + + @Override + public Observable.OnSubscribe onSubscribeStart(Observable observableInstance, + final Observable.OnSubscribe onSubscribe) { + int activeSubscriptionCount = subscriptions.incrementAndGet(); + Log.d(TAG, onSubscribe + " - onSubscribeStart: " + activeSubscriptionCount); + + return new Observable.OnSubscribe() { + @Override + public void call(final Subscriber subscriber) { + onSubscribe.call(new Subscriber() { + @Override + public void onCompleted() { + subscriber.onCompleted(); + onFinally(onSubscribe, "onCompleted"); + } + + @Override + public void onError(Throwable e) { + subscriber.onError(e); + onFinally(onSubscribe, "onError"); + } + + @Override + public void onNext(T t) { + subscriber.onNext(t); + } + }); + } + }; + } + + private void onFinally(Observable.OnSubscribe onSubscribe, final String finalizeCaller) { + int activeSubscriptionCount = subscriptions.decrementAndGet(); + Log.d(TAG, onSubscribe + " - " + finalizeCaller + ": " + activeSubscriptionCount); + + if (activeSubscriptionCount == 0) { + Log.d(TAG, "onTransitionToIdle"); + resourceCallback.onTransitionToIdle(); + } + } +} \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/androidTest/java/com/boredream/designrescollection/ui/login/LoginActivityTest.java b/DesignResCollection_MVP-Dagger2/app/src/androidTest/java/com/boredream/designrescollection/ui/login/LoginActivityTest.java new file mode 100644 index 0000000..2d73257 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/androidTest/java/com/boredream/designrescollection/ui/login/LoginActivityTest.java @@ -0,0 +1,117 @@ +package com.boredream.designrescollection.ui.login; + +import android.content.Intent; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.idlingres.RxIdlingResource; +import com.boredream.designrescollection.utils.UserInfoKeeper; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import rx.plugins.RxJavaPlugins; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; +import static android.support.test.espresso.action.ViewActions.typeText; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.RootMatchers.withDecorView; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; + +@RunWith(AndroidJUnit4.class) +public class LoginActivityTest { + + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule(LoginActivity.class, true, false); + + static { + RxJavaPlugins.getInstance().registerObservableExecutionHook(RxIdlingResource.get()); + } + + @Test + public void testLogin_EmptyPassword() throws Exception { + Intent intent = new Intent(); + mActivityRule.launchActivity(intent); + + // actions + onView(withId(R.id.et_username)).perform(typeText("13913391521"), closeSoftKeyboard()); + onView(withId(R.id.et_password)).perform(typeText(""), closeSoftKeyboard()); + onView(withId(R.id.btn_login)).perform(click()); + + // assertions + onView(withId(android.R.id.message)) + .inRoot(withDecorView(not(is(mActivityRule.getActivity().getWindow().getDecorView())))) + .check(matches(withText("密码不能为空"))); + } + + @Test + public void testLogin_EmptyUsername() throws Exception { + Intent intent = new Intent(); + mActivityRule.launchActivity(intent); + + // actions + onView(withId(R.id.et_username)).perform(typeText(""), closeSoftKeyboard()); + onView(withId(R.id.et_password)).perform(typeText("123456"), closeSoftKeyboard()); + onView(withId(R.id.btn_login)).perform(click()); + + // assertions + onView(withId(android.R.id.message)) + .inRoot(withDecorView(not(is(mActivityRule.getActivity().getWindow().getDecorView())))) + .check(matches(withText("用户名不能为空"))); + } + + @Test + public void testLogin_Success() throws Exception { + Intent intent = new Intent(); + intent.putExtra("checkLogin", true); + mActivityRule.launchActivity(intent); + + // actions + onView(withId(R.id.et_username)).perform(typeText("18551681236"), closeSoftKeyboard()); + onView(withId(R.id.et_password)).perform(typeText("123456"), closeSoftKeyboard()); + onView(withId(R.id.btn_login)).perform(click()); + + // assertions + Assert.assertTrue(UserInfoKeeper.getCurrentUser() != null); + } + + @Test + public void testLogin_UserNotExit() throws Exception { + Intent intent = new Intent(); + mActivityRule.launchActivity(intent); + + // actions + onView(withId(R.id.et_username)).perform(typeText("110110110"), closeSoftKeyboard()); + onView(withId(R.id.et_password)).perform(typeText("123456"), closeSoftKeyboard()); + onView(withId(R.id.btn_login)).perform(click()); + + // assertions + onView(withId(android.R.id.message)) + .inRoot(withDecorView(not(is(mActivityRule.getActivity().getWindow().getDecorView())))) + .check(matches(withText("找不到用户"))); + } + + @Test + public void testLogin_PswError() throws Exception { + Intent intent = new Intent(); + mActivityRule.launchActivity(intent); + + // actions + onView(withId(R.id.et_username)).perform(typeText("18551681236"), closeSoftKeyboard()); + onView(withId(R.id.et_password)).perform(typeText("110"), closeSoftKeyboard()); + onView(withId(R.id.btn_login)).perform(click()); + + // assertions + onView(withId(android.R.id.message)) + .inRoot(withDecorView(not(is(mActivityRule.getActivity().getWindow().getDecorView())))) + .check(matches(withText("密码不正确"))); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/androidTest/java/com/boredream/designrescollection/ui/userinfoedit/UserInfoEditActivityTest.java b/DesignResCollection_MVP-Dagger2/app/src/androidTest/java/com/boredream/designrescollection/ui/userinfoedit/UserInfoEditActivityTest.java new file mode 100644 index 0000000..d5fae18 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/androidTest/java/com/boredream/designrescollection/ui/userinfoedit/UserInfoEditActivityTest.java @@ -0,0 +1,95 @@ +package com.boredream.designrescollection.ui.userinfoedit; + +import android.app.Activity; +import android.app.Instrumentation; +import android.content.Intent; +import android.net.Uri; +import android.support.test.espresso.intent.Intents; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.entity.User; +import com.boredream.designrescollection.idlingres.RxIdlingResource; +import com.boredream.designrescollection.utils.UserInfoKeeper; + +import org.hamcrest.core.IsNot; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Random; + +import rx.plugins.RxJavaPlugins; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; +import static android.support.test.espresso.action.ViewActions.typeText; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.intent.Intents.intending; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasAction; +import static android.support.test.espresso.matcher.RootMatchers.withDecorView; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static org.hamcrest.core.Is.is; + +@RunWith(AndroidJUnit4.class) +public class UserInfoEditActivityTest { + + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule(UserInfoEditActivity.class, true, true); + + static { + User user = new User(); + user.setObjectId("57abf85e2e958a00543737da"); + user.setUsername("18551681236"); + user.setNickname(""); + user.setSessionToken("hh45pryl55lbm6n3l6sfbuywg"); + UserInfoKeeper.setCurrentUser(user); + + RxJavaPlugins.getInstance().registerObservableExecutionHook(RxIdlingResource.get()); + } + + @Test + public void testUploadAvatar() throws Exception { + Intents.init(); + + // Stub the Intent. + Instrumentation.ActivityResult resultGallery = createImageGalleryActivityResultStub(); + intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(resultGallery); + + // actions + onView(withId(R.id.ll_avatar)).perform(click()); + onView(withText("相册")) + .inRoot(withDecorView(IsNot.not(is(mActivityRule.getActivity().getWindow().getDecorView())))) + .perform(click()); + + // assertions + Assert.assertTrue(UserInfoKeeper.getCurrentUser().getAvatar() != null); + } + + private Instrumentation.ActivityResult createImageGalleryActivityResultStub() { + Uri uri = Uri.parse("file:///android_asset/test_avatar.jpg"); + + Intent resultData = new Intent(); + resultData.setData(uri); + + // Create the ActivityResult with the Intent. + return new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData); + } + + @Test + public void testUpdateNickname() throws Exception { + String newName = "boredream" + new Random().nextInt(10); + + // actions + onView(withId(R.id.ll_username)).perform(click()); + onView(withId(R.id.et_input)).perform(typeText(newName), closeSoftKeyboard()); + onView(withText("保存")).perform(click()); + + // assertions + onView(withId(R.id.tv_username)).check(matches(withText(newName))); + } +} \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/AndroidManifest.xml b/DesignResCollection_MVP-Dagger2/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c7f869a --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/assets/test_avatar.jpg b/DesignResCollection_MVP-Dagger2/app/src/main/assets/test_avatar.jpg new file mode 100644 index 0000000..8208ec9 Binary files /dev/null and b/DesignResCollection_MVP-Dagger2/app/src/main/assets/test_avatar.jpg differ diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/adapter/DesignResAdapter.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/adapter/DesignResAdapter.java new file mode 100644 index 0000000..b8b72dc --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/adapter/DesignResAdapter.java @@ -0,0 +1,73 @@ +package com.boredream.designrescollection.adapter; + +import android.content.Context; +import android.content.Intent; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.boredream.bdcodehelper.activity.WebViewActivity; +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.entity.DesignRes; +import com.boredream.designrescollection.net.GlideHelper; + +import java.util.ArrayList; + +public class DesignResAdapter extends RecyclerView.Adapter { + + private Context context; + private ArrayList datas; + + public DesignResAdapter(Context context, ArrayList datas) { + this.context = context; + this.datas = datas; + } + + @Override + public int getItemCount() { + return datas.size(); + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + public ImageView iv_image; + public TextView tv_name; + + public ViewHolder(View rootView) { + super(rootView); + + this.iv_image = (ImageView) rootView.findViewById(R.id.iv_image); + this.tv_name = (TextView) rootView.findViewById(R.id.tv_name); + } + + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View v = LayoutInflater.from(context).inflate(R.layout.item_design_res, parent, false); + return new ViewHolder(v); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + final DesignRes data = datas.get(position); + + GlideHelper.showImage(context, data.getImgUrl(), holder.iv_image); + String str = String.format("[%s] %s", data.getSrcTag(), data.getName()); + holder.tv_name.setText(str); + + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(context, WebViewActivity.class); + intent.putExtra(WebViewActivity.EXTRA_TITLE, data.getName()); + intent.putExtra(WebViewActivity.EXTRA_URL, data.getSrcLink()); + context.startActivity(intent); + } + }); + } + + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/adapter/MoreRecyclerAdapter.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/adapter/MoreRecyclerAdapter.java new file mode 100644 index 0000000..8c2215b --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/adapter/MoreRecyclerAdapter.java @@ -0,0 +1,126 @@ +package com.boredream.designrescollection.adapter; + +import android.content.Intent; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import com.boredream.bdcodehelper.adapter.SettingRecyclerAdapter; +import com.boredream.bdcodehelper.entity.SettingItem; +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.entity.User; +import com.boredream.designrescollection.net.GlideHelper; +import com.boredream.designrescollection.ui.login.LoginActivity; + +import java.util.List; + +/** + * 更多选项列表适配器 + *

+ * 第一个位置为HEADER类型,对应用户信息
+ * 其他位置为LIST类型,对应选项item + */ +public class MoreRecyclerAdapter extends SettingRecyclerAdapter { + + private static final int ITEM_VIEW_TYPE_HEADER = 0; + + private User user; + + public MoreRecyclerAdapter(List datas, OnItemClickListener listener) { + super(datas, listener); + } + + @Override + public int getItemCount() { + // header + 1 + return datas.size() + 1; + } + + @Override + public int getItemViewType(int position) { + return position == 0 ? ITEM_VIEW_TYPE_HEADER : super.getItemViewType(position); + } + + public void setUser(User user) { + this.user = user; + } + + public static class ViewHolderUserHeader extends RecyclerView.ViewHolder { + + public View include_more_header; + public ImageView iv_avatar; + public TextView tv_name; + // not login + public View include_more_no_header; + public Button btn_login; + + public ViewHolderUserHeader(final View itemView) { + super(itemView); + + include_more_header = itemView.findViewById(R.id.include_more_header); + iv_avatar = (ImageView) itemView.findViewById(R.id.iv_avatar); + tv_name = (TextView) itemView.findViewById(R.id.tv_name); + include_more_no_header = itemView.findViewById(R.id.include_more_no_header); + btn_login = (Button) itemView.findViewById(R.id.btn_login); + } + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + if (viewType == ITEM_VIEW_TYPE_HEADER) { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_more_header, parent, false); + return new ViewHolderUserHeader(v); + } else { + return super.onCreateViewHolder(parent, viewType); + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { + int itemViewType = getItemViewType(position); + if (itemViewType == ITEM_VIEW_TYPE_HEADER) { + // header + ViewHolderUserHeader viewHolderHeader = (ViewHolderUserHeader) holder; + if (user != null) { + // 如果已登录,用户数据非空,则显示用户信息 + viewHolderHeader.include_more_header.setVisibility(View.VISIBLE); + viewHolderHeader.include_more_no_header.setVisibility(View.GONE); + + GlideHelper.showAvatar(holder.itemView.getContext(), user.getAvatar(), viewHolderHeader.iv_avatar); + viewHolderHeader.tv_name.setText(user.getNickname()); + + viewHolderHeader.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (mOnItemClickListener != null) { + // header使用特殊的position -1 + mOnItemClickListener.onItemClick(null, view, -1, -1); + } + } + }); + } else { + // 未登录,提供登录按钮,点击进入登录页 + viewHolderHeader.include_more_header.setVisibility(View.GONE); + viewHolderHeader.include_more_no_header.setVisibility(View.VISIBLE); + + viewHolderHeader.btn_login.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(view.getContext(), LoginActivity.class); + view.getContext().startActivity(intent); + } + }); + } + } else { + // setting item + // 第一个位置多了个HEADER,所以position差1 + super.onBindViewHolder(holder, position - 1); + } + } + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseActivity.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseActivity.java new file mode 100644 index 0000000..9da6d5a --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseActivity.java @@ -0,0 +1,103 @@ +package com.boredream.designrescollection.base; + + +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; + +import com.boredream.bdcodehelper.base.BoreBaseActivity; +import com.boredream.designrescollection.constants.CommonConstants; +import com.boredream.designrescollection.ui.MainActivity; + +import java.util.concurrent.TimeUnit; + +import rx.Observable; +import rx.functions.Action1; + +public class BaseActivity extends BoreBaseActivity { + + public BaseApplication application; + public SharedPreferences sp; + + private boolean couldDoubleBackExit; + private boolean doubleBackExitPressedOnce; + + protected boolean isActive; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // 如果是退出应用flag,则直接关闭当前页面,不加载UI + boolean exit = getIntent().getBooleanExtra("exit", false); + if (exit) { + finish(); + return; + } + + application = (BaseApplication) getApplication(); + sp = getSharedPreferences(CommonConstants.SP_NAME, MODE_PRIVATE); + } + + @Override + protected void onStart() { + super.onStart(); + isActive = true; + } + + @Override + protected void onStop() { + super.onStop(); + isActive = false; + } + + /** + * 设置是否可以双击返回退出,需要有该功能的页面set true即可 + * + * @param couldDoubleBackExit true-开启双击退出 + */ + public void setCouldDoubleBackExit(boolean couldDoubleBackExit) { + this.couldDoubleBackExit = couldDoubleBackExit; + } + + @Override + public void onBackPressed() { + if (!couldDoubleBackExit) { + // 非双击退出状态,使用原back逻辑 + super.onBackPressed(); + return; + } + + // 双击返回键关闭程序 + // 如果两秒重置时间内再次点击返回,则退出程序 + if (doubleBackExitPressedOnce) { + exit(); + return; + } + + doubleBackExitPressedOnce = true; + showToast("再按一次返回键关闭程序"); + Observable.just(null) + .delay(2, TimeUnit.SECONDS) + .subscribe(new Action1() { + @Override + public void call(Object o) { + // 延迟两秒后重置标志位为false + doubleBackExitPressedOnce = false; + } + }); + } + + /** + * 退出程序 + */ + protected void exit() { + // 退出程序方法有多种 + // 这里使用clear + new task的方式清空整个任务栈,只保留新打开的Main页面 + // 然后Main页面接收到退出的标志位exit=true,finish自己,这样就关闭了全部页面 + Intent intent = new Intent(this, MainActivity.class); + intent.putExtra("exit", true); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseApplication.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseApplication.java new file mode 100644 index 0000000..a61961e --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseApplication.java @@ -0,0 +1,72 @@ +package com.boredream.designrescollection.base; + + +import android.app.Application; + +import com.boredream.designrescollection.net.DaggerAppComponent; +import com.boredream.designrescollection.utils.UserInfoKeeper; +import com.bumptech.glide.Glide; +import com.bumptech.glide.integration.okhttp.OkHttpUrlLoader; +import com.bumptech.glide.load.model.GlideUrl; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; +import com.squareup.okhttp.logging.HttpLoggingInterceptor; + +import java.io.IOException; +import java.io.InputStream; + +public class BaseApplication extends Application { + + private static final String APP_ID_NAME = "X-LC-Id"; + private static final String API_KEY_NAME = "X-LC-Key"; + public static final String SESSION_TOKEN_KEY = "X-LC-Session"; + + private static final String APP_ID_VALUE = "iaEH7ObIA4sPY8RSs3VCVXBg-gzGzoHsz"; + private static final String API_KEY_VALUE = "dXfhXIVyeWMN2czJkd4ehwzs"; + + private OkHttpClient okHttpClient; + + @Override + public void onCreate() { + super.onCreate(); + + initOkHttpClient(); + initGlide(); + } + + private void initOkHttpClient() { + // OkHttpClient + okHttpClient = new OkHttpClient(); + + // 统一添加的Header + okHttpClient.networkInterceptors().add(new Interceptor() { + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request().newBuilder() + .addHeader("Content-Type", "application/json") + .addHeader(APP_ID_NAME, APP_ID_VALUE) + .addHeader(API_KEY_NAME, API_KEY_VALUE) + .addHeader(SESSION_TOKEN_KEY, UserInfoKeeper.getToken()) + .build(); + return chain.proceed(request); + } + }); + + // log + HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); + okHttpClient.interceptors().add(interceptor); + } + + /** + * 图片加载框架Glide,使用OkHttp处理网络请求 + */ + private void initGlide() { + DaggerAppComponent.builder().build().inject(this); + + Glide.get(this).register(GlideUrl.class, InputStream.class, + new OkHttpUrlLoader.Factory(okHttpClient)); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseEntity.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseEntity.java new file mode 100644 index 0000000..2755d61 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseEntity.java @@ -0,0 +1,16 @@ +package com.boredream.designrescollection.base; + + +import com.boredream.bdcodehelper.base.BoreBaseEntity; + +public class BaseEntity extends BoreBaseEntity { + + @Override + public boolean equals(Object o) { + if (o instanceof BaseEntity) { + BaseEntity oEntity = (BaseEntity) o; + return this.objectId.equals(oEntity.objectId); + } + return super.equals(o); + } +} \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseFragment.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseFragment.java new file mode 100644 index 0000000..6203438 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseFragment.java @@ -0,0 +1,48 @@ +package com.boredream.designrescollection.base; + + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.widget.Toast; + +import com.boredream.bdcodehelper.utils.ToastUtils; + +public abstract class BaseFragment extends Fragment { + + protected String TAG; + protected BaseActivity activity; + // progressDialog/sp/application 等使用activity.xx 调用 + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + TAG = getClass().getSimpleName(); + + activity = (BaseActivity) getActivity(); + } + + protected void intent2Activity(Class tarActivity) { + Intent intent = new Intent(activity, tarActivity); + startActivity(intent); + } + + protected void showToast(String msg) { + ToastUtils.showToast(activity, msg, Toast.LENGTH_SHORT); + } + + protected void showLog(String msg) { + Log.i(TAG, msg); + } + + protected void showProgressDialog() { + activity.showProgressDialog(); + } + + protected void dismissProgressDialog() { + activity.dismissProgressDialog(); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BasePresenter.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BasePresenter.java new file mode 100644 index 0000000..2d46304 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BasePresenter.java @@ -0,0 +1,21 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.boredream.designrescollection.base; + +public interface BasePresenter { + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseView.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseView.java new file mode 100644 index 0000000..7e0b7f7 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/base/BaseView.java @@ -0,0 +1,31 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.boredream.designrescollection.base; + +public interface BaseView { + + void setPresenter(T presenter); + + boolean isActive(); + + void showProgress(); + + void dismissProgress(); + + void showTip(String message); + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/constants/CommonConstants.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/constants/CommonConstants.java new file mode 100644 index 0000000..56ec2d0 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/constants/CommonConstants.java @@ -0,0 +1,21 @@ +package com.boredream.designrescollection.constants; + +/** + * 通用常量 + */ +public class CommonConstants { + + private CommonConstants() { + } + + /** + * SharedPreferences 名称 + */ + public static final String SP_NAME = "config"; + + /** + * 每页加载的数量 + */ + public static final int COUNT_OF_PAGE = 20; + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/entity/Comment.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/entity/Comment.java new file mode 100644 index 0000000..6983bed --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/entity/Comment.java @@ -0,0 +1,45 @@ +package com.boredream.designrescollection.entity; + + +import com.boredream.designrescollection.base.BaseEntity; + +public class Comment extends BaseEntity { + /** + * 所属资源 + */ + private DesignRes designRes; + + /** + * 发送用户, Pointer or User + */ + private User user; + + /** + * 评论内容 + */ + private String content; + + public DesignRes getDesignRes() { + return designRes; + } + + public void setDesignRes(DesignRes designRes) { + this.designRes = designRes; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/entity/DesignRes.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/entity/DesignRes.java new file mode 100644 index 0000000..e2ef953 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/entity/DesignRes.java @@ -0,0 +1,84 @@ +package com.boredream.designrescollection.entity; + + +import com.boredream.designrescollection.base.BaseEntity; + +/** + * 设计资源 + */ +public class DesignRes extends BaseEntity { + + private String desc; + private String srcTag; + private String name; + private String imgUrl; + private String srcLink; + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public String getSrcTag() { + return srcTag; + } + + public void setSrcTag(String srcTag) { + this.srcTag = srcTag; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getImgUrl() { + return imgUrl; + } + + public void setImgUrl(String imgUrl) { + this.imgUrl = imgUrl; + } + + public String getSrcLink() { + return srcLink; + } + + public void setSrcLink(String srcLink) { + this.srcLink = srcLink; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + + DesignRes designRes = (DesignRes) o; + + if (desc != null ? !desc.equals(designRes.desc) : designRes.desc != null) return false; + if (srcTag != null ? !srcTag.equals(designRes.srcTag) : designRes.srcTag != null) + return false; + if (name != null ? !name.equals(designRes.name) : designRes.name != null) return false; + if (imgUrl != null ? !imgUrl.equals(designRes.imgUrl) : designRes.imgUrl != null) + return false; + return srcLink != null ? srcLink.equals(designRes.srcLink) : designRes.srcLink == null; + + } + + @Override + public int hashCode() { + int result = desc != null ? desc.hashCode() : 0; + result = 31 * result + (srcTag != null ? srcTag.hashCode() : 0); + result = 31 * result + (name != null ? name.hashCode() : 0); + result = 31 * result + (imgUrl != null ? imgUrl.hashCode() : 0); + result = 31 * result + (srcLink != null ? srcLink.hashCode() : 0); + return result; + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/entity/FeedBack.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/entity/FeedBack.java new file mode 100644 index 0000000..2d1ac6b --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/entity/FeedBack.java @@ -0,0 +1,27 @@ +package com.boredream.designrescollection.entity; + + +import com.boredream.designrescollection.base.BaseEntity; + +public class FeedBack extends BaseEntity { + + private String content; + private String email; + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + +} \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/entity/User.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/entity/User.java new file mode 100644 index 0000000..40dbcfe --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/entity/User.java @@ -0,0 +1,99 @@ +package com.boredream.designrescollection.entity; + + +import com.boredream.designrescollection.base.BaseEntity; + +public class User extends BaseEntity { + + private String sessionToken; + + private String nickname; + + private String username; + + /** + * 验证手机号 + */ + private String mobilePhoneNumber; + + /** + * 密码 + */ + private String password; + + /** + * 手机号验证码,发送短信验证时请求使用 + */ + private String smsCode; + + /** + * 头像图片地址 + */ + private String avatar; + + private String company; + + public String getSessionToken() { + return sessionToken; + } + + public void setSessionToken(String sessionToken) { + this.sessionToken = sessionToken; + } + + public String getCompany() { + return company; + } + + public void setCompany(String company) { + this.company = company; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getSmsCode() { + return smsCode; + } + + public void setSmsCode(String smsCode) { + this.smsCode = smsCode; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getMobilePhoneNumber() { + return mobilePhoneNumber; + } + + public void setMobilePhoneNumber(String mobilePhoneNumber) { + this.mobilePhoneNumber = mobilePhoneNumber; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/ApiModule.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/ApiModule.java new file mode 100644 index 0000000..494229a --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/ApiModule.java @@ -0,0 +1,33 @@ +package com.boredream.designrescollection.net; + +import com.squareup.okhttp.OkHttpClient; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; +import retrofit.GsonConverterFactory; +import retrofit.Retrofit; +import retrofit.RxJavaCallAdapterFactory; + +@Module +public class ApiModule { + + // LeanCloud + public static final String HOST = "https://api.leancloud.cn"; + + @Singleton + @Provides + ApiService provideApiService(OkHttpClient httpClient) { + // Retrofit + Retrofit retrofit = new Retrofit.Builder() + .baseUrl(HOST) + .addConverterFactory(GsonConverterFactory.create()) // gson + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // rxjava + .client(httpClient) + .build(); + + return retrofit.create(ApiService.class); + } + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/ApiService.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/ApiService.java new file mode 100644 index 0000000..59f8e47 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/ApiService.java @@ -0,0 +1,64 @@ +package com.boredream.designrescollection.net; + +import com.boredream.bdcodehelper.entity.AppUpdateInfo; +import com.boredream.bdcodehelper.entity.FileUploadResponse; +import com.boredream.bdcodehelper.entity.ListResponse; +import com.boredream.designrescollection.base.BaseEntity; +import com.boredream.designrescollection.entity.DesignRes; +import com.boredream.designrescollection.entity.FeedBack; +import com.boredream.designrescollection.entity.User; +import com.squareup.okhttp.RequestBody; + +import java.util.Map; + +import retrofit.http.Body; +import retrofit.http.GET; +import retrofit.http.POST; +import retrofit.http.PUT; +import retrofit.http.Path; +import retrofit.http.Query; +import rx.Observable; + +public interface ApiService { + ////////////////////////////// 通用接口 ////////////////////////////// + // 登录用户 + @GET("/1/login") + Observable login( + @Query("username") String username, + @Query("password") String password); + + // 注册用户 + @POST("/1/users") + Observable register( + @Body User user); + + // 修改用户详情(注意, 提交什么参数修改什么参数) + @PUT("/1/users/{objectId}") + Observable updateUserById( + @Path("objectId") String userId, + @Body Map updateInfo); + + // 上传图片接口 + @POST("/1/files/{fileName}") + Observable fileUpload( + @Path("fileName") String fileName, + @Body RequestBody image); + + // 查询app更新信息 + @GET("/1/classes/AppUpdateInfo") + Observable> getAppUpdateInfo(); + + // 提交意见反馈 + @POST("/1/classes/FeedBack") + Observable addFeedBack( + @Body FeedBack feedBack); + + + ////////////////////////////// 业务接口 ////////////////////////////// + + // 查询设计资源 + @GET("/1/classes/DesignRes") + Observable> getDesignRes( + @Query("limit") int perPageCount, + @Query("skip") int page); +} \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/AppComponent.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/AppComponent.java new file mode 100644 index 0000000..f84120c --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/AppComponent.java @@ -0,0 +1,17 @@ +package com.boredream.designrescollection.net; + +import com.boredream.designrescollection.base.BaseApplication; +import com.boredream.designrescollection.utils.PerApplication; + +import javax.inject.Singleton; + +import dagger.Component; + +@PerApplication +@Singleton +@Component(modules = {ApiModule.class}) +public interface AppComponent { + + void inject(BaseApplication request); + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/GlideHelper.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/GlideHelper.java new file mode 100644 index 0000000..f0d9c92 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/GlideHelper.java @@ -0,0 +1,36 @@ +package com.boredream.designrescollection.net; + + +import android.content.Context; +import android.widget.ImageView; + +import com.boredream.bdcodehelper.net.GlideCircleTransform; +import com.boredream.designrescollection.R; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; + +/** + * Glide + */ +public class GlideHelper { + + public static void showAvatar(Context context, String avatar, ImageView iv) { + Glide.with(context) + .load(avatar) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .placeholder(R.mipmap.ic_account_circle_grey600_24dp) + .error(R.mipmap.ic_account_circle_grey600_24dp) + .transform(new GlideCircleTransform(context)) + .crossFade() + .into(iv); + } + + public static void showImage(Context context, String imageUrl, ImageView iv) { + Glide.with(context) + .load(imageUrl) + .asBitmap() + .animate(android.R.anim.fade_in) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .into(iv); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/SimpleSubscriber.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/SimpleSubscriber.java new file mode 100644 index 0000000..2364599 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/net/SimpleSubscriber.java @@ -0,0 +1,40 @@ +package com.boredream.designrescollection.net; + + +import android.content.Context; + +import com.boredream.bdcodehelper.utils.ErrorInfoUtils; +import com.boredream.bdcodehelper.utils.ToastUtils; + +import rx.Subscriber; + +/** + * 通用订阅者,用于统一处理回调 + */ +public class SimpleSubscriber extends Subscriber { + + private Context context; + + public SimpleSubscriber(Context context) { + this.context = context; + } + + @Override + public void onCompleted() { + // sub + } + + @Override + public void onError(Throwable throwable) { + // 统一处理错误回调,显示Toast + String errorInfo = ErrorInfoUtils.parseHttpErrorInfo(throwable); + ToastUtils.showToast(context, errorInfo); + } + + @Override + public void onNext(T t) { + // sub + } + + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/AboutActivity.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/AboutActivity.java new file mode 100644 index 0000000..9c5973a --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/AboutActivity.java @@ -0,0 +1,58 @@ +package com.boredream.designrescollection.ui; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; +import android.view.View; +import android.widget.TextView; + +import com.boredream.bdcodehelper.utils.AppUtils; +import com.boredream.bdcodehelper.utils.StringUtils; +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.base.BaseActivity; + +public class AboutActivity extends BaseActivity { + + private TextView tv_version; + private TextView tv_about; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_about); + initView(); + } + + private void initView() { + initBackTitle("关于我"); + + tv_version = (TextView) findViewById(R.id.tv_version); + tv_about = (TextView) findViewById(R.id.tv_about); + + tv_version.setText("Version " + AppUtils.getAppVersionName(this)); + + SpannableString ss = getAboutString(); + tv_about.setMovementMethod(LinkMovementMethod.getInstance()); + tv_about.setText(ss); + } + + private SpannableString getAboutString() { + final String githubLink = getString(R.string.github); + String format = String.format(getString(R.string.about), githubLink); + SpannableString ss = new SpannableString(format); + // 网址部分可点击,跳转到网页 + StringUtils.PrimaryClickableSpan span = new StringUtils.PrimaryClickableSpan(this) { + @Override + public void onClick(View widget) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(githubLink)); + startActivity(intent); + } + }; + int start = format.indexOf(githubLink); + ss.setSpan(span, start, start + githubLink.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + return ss; + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/MainActivity.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/MainActivity.java new file mode 100644 index 0000000..b4d5eb8 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/MainActivity.java @@ -0,0 +1,72 @@ +package com.boredream.designrescollection.ui; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.widget.RadioButton; +import android.widget.RadioGroup; + +import com.boredream.bdcodehelper.fragment.FragmentController; +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.base.BaseActivity; +import com.boredream.designrescollection.net.ApiService; +import com.boredream.designrescollection.ui.home.HomeFragment; +import com.boredream.designrescollection.utils.UpdateUtils; + +import java.util.ArrayList; + +import javax.inject.Inject; + + +public class MainActivity extends BaseActivity implements RadioGroup.OnCheckedChangeListener { + + @Inject ApiService service; + + private RadioGroup rg_bottom_tab; + private RadioButton rb1; + private FragmentController controller; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + initView(); + initData(); + } + + private void initView() { + setCouldDoubleBackExit(true); + + rg_bottom_tab = (RadioGroup) findViewById(R.id.rg_bottom_tab); + rb1 = (RadioButton) findViewById(R.id.rb1); + + rg_bottom_tab.setOnCheckedChangeListener(this); + } + + private void initData() { + ArrayList fragments = new ArrayList(); + fragments.add(new HomeFragment()); + fragments.add(new UserFragment()); + + controller = new FragmentController(this, R.id.fl_content, fragments); + + // 默认Fragment + rb1.setChecked(true); + controller.showFragment(0); + + UpdateUtils.checkUpdate(this, service.getAppUpdateInfo(), false); + } + + @Override + public void onCheckedChanged(RadioGroup radioGroup, int checkedId) { + switch (checkedId) { + case R.id.rb1: + controller.showFragment(0); + break; + case R.id.rb2: + controller.showFragment(1); + break; + } + } + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/SettingActivity.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/SettingActivity.java new file mode 100644 index 0000000..8adef4c --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/SettingActivity.java @@ -0,0 +1,105 @@ +package com.boredream.designrescollection.ui; + +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.AdapterView; +import android.widget.Button; + +import com.boredream.bdcodehelper.adapter.SettingRecyclerAdapter; +import com.boredream.bdcodehelper.entity.SettingItem; +import com.boredream.bdcodehelper.utils.AppUtils; +import com.boredream.bdcodehelper.view.DividerItemDecoration; +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.base.BaseActivity; +import com.boredream.designrescollection.net.ApiService; +import com.boredream.designrescollection.ui.feedback.FeedBackActivity; +import com.boredream.designrescollection.utils.UpdateUtils; +import com.boredream.designrescollection.utils.UserInfoKeeper; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +public class SettingActivity extends BaseActivity implements View.OnClickListener, AdapterView.OnItemClickListener { + + @Inject ApiService service; + private RecyclerView rv_setting; + private Button btn_logout; + + private SettingRecyclerAdapter adapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_setting); + initView(); + initData(); + } + + private void initView() { + initBackTitle("设置"); + + rv_setting = (RecyclerView) findViewById(R.id.rv_setting); + btn_logout = (Button) findViewById(R.id.btn_logout); + + btn_logout.setOnClickListener(this); + } + + private void initData() { + // 使用列表显示多个选项条 + List items = new ArrayList(); + + items.add(new SettingItem( + R.mipmap.ic_cached_grey600_24dp, + "检查更新", + AppUtils.getAppVersionName(this), + R.mipmap.ic_chevron_right_grey600_24dp + )); + items.add(new SettingItem( + R.mipmap.ic_announcement_grey600_24dp, + "反馈", + null, + R.mipmap.ic_chevron_right_grey600_24dp + )); + + adapter = new SettingRecyclerAdapter(items, this); + rv_setting.setAdapter(adapter); + + LinearLayoutManager linearLayoutManager = new LinearLayoutManager( + this, LinearLayoutManager.VERTICAL, false); + rv_setting.setLayoutManager(linearLayoutManager); + // 每个item之间的分割线 + rv_setting.addItemDecoration(new DividerItemDecoration(this)); + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + switch (position) { + case 0: + showProgressDialog(); + // 强制检查更新,并添加额外回调用于处理进度框 + UpdateUtils.checkUpdate(this, service.getAppUpdateInfo(), true); + break; + case 1: + if(UserInfoKeeper.checkLogin(this)) { + // 一般意见反馈不需要登录,这里模拟下需登录场景的处理方法 + intent2Activity(FeedBackActivity.class); + } + break; + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_logout: + // 登出,清理用户数据同时跳转到主页 + UserInfoKeeper.logout(); + intent2Activity(MainActivity.class); + break; + } + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/UserFragment.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/UserFragment.java new file mode 100644 index 0000000..3056455 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/UserFragment.java @@ -0,0 +1,98 @@ +package com.boredream.designrescollection.ui; + +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; + +import com.boredream.bdcodehelper.entity.SettingItem; +import com.boredream.bdcodehelper.utils.DisplayUtils; +import com.boredream.bdcodehelper.utils.TitleBuilder; +import com.boredream.bdcodehelper.view.DividerItemDecoration; +import com.boredream.bdcodehelper.view.EmptyItemDecoration; +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.adapter.MoreRecyclerAdapter; +import com.boredream.designrescollection.base.BaseFragment; +import com.boredream.designrescollection.ui.userinfoedit.UserInfoEditActivity; +import com.boredream.designrescollection.utils.UserInfoKeeper; + +import java.util.ArrayList; +import java.util.List; + +public class UserFragment extends BaseFragment implements AdapterView.OnItemClickListener { + + private RecyclerView rv_user; + private MoreRecyclerAdapter adapter; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = View.inflate(activity, R.layout.frag_user, null); + initView(view); + initData(); + return view; + } + + @Override + public void onStart() { + super.onStart(); + + // 如果未登录进入本页面,然后跳转登录页面成功后返回,此时应该再次更新用户信息 + adapter.setUser(UserInfoKeeper.getCurrentUser()); + adapter.notifyDataSetChanged(); + } + + private void initView(View view) { + new TitleBuilder(view).setTitleText("更多"); + + rv_user = (RecyclerView) view.findViewById(R.id.rv_user); + } + + private void initData() { + // more items + List items = new ArrayList(); + items.add(new SettingItem( + R.mipmap.ic_info_grey600_24dp, + "关于", + null, + R.mipmap.ic_chevron_right_grey600_24dp + )); + items.add(new SettingItem( + R.mipmap.ic_settings_grey600_24dp, + "设置", + null, + R.mipmap.ic_chevron_right_grey600_24dp + )); + + adapter = new MoreRecyclerAdapter(items, this); + rv_user.setAdapter(adapter); + + LinearLayoutManager linearLayoutManager = new LinearLayoutManager( + activity, LinearLayoutManager.VERTICAL, false); + rv_user.setLayoutManager(linearLayoutManager); + // 每个item之间的分割线 + rv_user.addItemDecoration(new DividerItemDecoration(activity)); + // 每组item之间的分割间隔 + rv_user.addItemDecoration(new EmptyItemDecoration( + new Integer[]{0, 1}, DisplayUtils.dp2px(activity, 16))); + + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + switch (position) { + case -1: + // 给特殊的用户信息header位置设为了position=-1的item click事件 + intent2Activity(UserInfoEditActivity.class); + break; + case 0: + intent2Activity(AboutActivity.class); + break; + case 1: + intent2Activity(SettingActivity.class); + break; + } + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/feedback/FeedBackActivity.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/feedback/FeedBackActivity.java new file mode 100644 index 0000000..c3a4b3d --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/feedback/FeedBackActivity.java @@ -0,0 +1,85 @@ +package com.boredream.designrescollection.ui.feedback; + + +import android.os.Bundle; +import android.view.View; +import android.widget.EditText; + +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.base.BaseActivity; +import com.boredream.designrescollection.net.ApiService; + +import javax.inject.Inject; + +public class FeedBackActivity extends BaseActivity implements FeedBackContract.View { + + private FeedBackContract.Presenter presenter; + private EditText et_content; + private EditText et_email; + @Inject ApiService service; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_feed_back); + + initView(); + } + + private void initView() { + presenter = new FeedBackPresenter(this, service); + + initBackTitle("意见反馈") + .setRightText("提交") + .setRightOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + submit(); + } + }); + + et_content = (EditText) findViewById(R.id.et_content); + et_email = (EditText) findViewById(R.id.et_email); + + } + + private void submit() { + // 开始验证输入内容 + String content = et_content.getText().toString().trim(); + String email = et_email.getText().toString().trim(); + + presenter.addFeedback(content, email); + } + + @Override + public void addFeedbackSuccess() { + showToast("反馈成功"); + finish(); + } + + @Override + public void setPresenter(FeedBackContract.Presenter presenter) { + this.presenter = presenter; + } + + @Override + public boolean isActive() { + return isActive; + } + + @Override + public void showProgress() { + showProgressDialog(); + } + + @Override + public void dismissProgress() { + dismissProgressDialog(); + } + + @Override + public void showTip(String message) { + showToast(message); + } +} \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/feedback/FeedBackContract.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/feedback/FeedBackContract.java new file mode 100644 index 0000000..95ae757 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/feedback/FeedBackContract.java @@ -0,0 +1,19 @@ +package com.boredream.designrescollection.ui.feedback; + +import com.boredream.designrescollection.base.BasePresenter; +import com.boredream.designrescollection.base.BaseView; + +public interface FeedBackContract { + + interface View extends BaseView { + + void addFeedbackSuccess(); + + } + + interface Presenter extends BasePresenter { + + void addFeedback(String content, String email); + + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/feedback/FeedBackPresenter.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/feedback/FeedBackPresenter.java new file mode 100644 index 0000000..d92e958 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/feedback/FeedBackPresenter.java @@ -0,0 +1,71 @@ +package com.boredream.designrescollection.ui.feedback; + +import com.boredream.bdcodehelper.net.ObservableDecorator; +import com.boredream.bdcodehelper.utils.StringUtils; +import com.boredream.designrescollection.base.BaseEntity; +import com.boredream.designrescollection.entity.FeedBack; +import com.boredream.designrescollection.net.ApiService; + +import rx.Observable; +import rx.Subscriber; + +public class FeedBackPresenter implements FeedBackContract.Presenter { + + private final FeedBackContract.View view; + private final ApiService api; + + public FeedBackPresenter(FeedBackContract.View view, ApiService api) { + this.view = view; + this.api = api; + this.view.setPresenter(this); + } + + @Override + public void addFeedback(String content, String email) { + // 开始验证输入内容 + if (StringUtils.isEmpty(content)) { + view.showTip("反馈内容不能为空"); + return; + } + + if (StringUtils.isEmpty(email)) { + view.showTip("请输入邮箱地址,方便我们对您的意见进行及时回复"); + return; + } + + view.showProgress(); + + // 使用自定义对象存至云平台,作为简易版的反馈意见收集 + FeedBack fb = new FeedBack(); + fb.setContent(content); + fb.setEmail(email); + + Observable observable = ObservableDecorator.decorate(api.addFeedBack(fb)); + observable.subscribe(new Subscriber() { + @Override + public void onCompleted() { + + } + + @Override + public void onError(Throwable e) { + if (!view.isActive()) { + return; + } + view.dismissProgress(); + + view.showTip("反馈提交失败"); + } + + @Override + public void onNext(BaseEntity entity) { + if (!view.isActive()) { + return; + } + view.dismissProgress(); + + view.addFeedbackSuccess(); + } + }); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/home/HomeContract.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/home/HomeContract.java new file mode 100644 index 0000000..2f830ee --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/home/HomeContract.java @@ -0,0 +1,24 @@ +package com.boredream.designrescollection.ui.home; + +import com.boredream.designrescollection.base.BasePresenter; +import com.boredream.designrescollection.base.BaseView; +import com.boredream.designrescollection.entity.DesignRes; + +import java.util.List; + +public interface HomeContract { + + interface View extends BaseView { + + void loadListSuccess(int page, List datas); + + } + + interface Presenter extends BasePresenter { + + void loadList(int page); + + void pullToLoadList(); + + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/home/HomeFragment.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/home/HomeFragment.java new file mode 100644 index 0000000..1ab64c5 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/home/HomeFragment.java @@ -0,0 +1,120 @@ +package com.boredream.designrescollection.ui.home; + + +import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.boredream.bdcodehelper.adapter.LoadMoreAdapter; +import com.boredream.bdcodehelper.utils.DisplayUtils; +import com.boredream.bdcodehelper.utils.TitleBuilder; +import com.boredream.bdcodehelper.view.GridSpacingDecorator; +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.adapter.DesignResAdapter; +import com.boredream.designrescollection.base.BaseFragment; +import com.boredream.designrescollection.constants.CommonConstants; +import com.boredream.designrescollection.entity.DesignRes; + +import java.util.ArrayList; +import java.util.List; + +public class HomeFragment extends BaseFragment implements HomeContract.View { + + private View view; + private SwipeRefreshLayout srl; + private RecyclerView rv; + + private HomeContract.Presenter presenter; + private int curPage = 1; + private ArrayList datas = new ArrayList(); + private LoadMoreAdapter adapter; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + view = View.inflate(activity, R.layout.frag_home, null); + initView(); + initData(); + return view; + } + + private void initView() { + presenter = new HomePresenter(this); + new TitleBuilder(view).setTitleText(getString(R.string.tab1)); + + srl = (SwipeRefreshLayout) view.findViewById(R.id.srl); + srl.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + presenter.pullToLoadList(); + } + }); + + rv = (RecyclerView) view.findViewById(R.id.rv); + rv.addItemDecoration(new GridSpacingDecorator(DisplayUtils.dp2px(activity, 8))); + GridLayoutManager gridLayoutManager = new GridLayoutManager(activity, 2); + rv.setLayoutManager(gridLayoutManager); + + adapter = new LoadMoreAdapter(rv, + new DesignResAdapter(activity, datas), + new LoadMoreAdapter.OnLoadMoreListener() { + @Override + public void onLoadMore() { + presenter.loadList(curPage + 1); + } + }); + rv.setAdapter(adapter); + } + + private void initData() { + presenter.loadList(1); + } + + @Override + public void loadListSuccess(int page, List datas) { + curPage = page; + if (curPage == 1) { + this.datas.clear(); + } + this.datas.addAll(datas); + + // 设置是否已加载完全部数据状态 + adapter.setStatus(datas.size() == CommonConstants.COUNT_OF_PAGE + ? LoadMoreAdapter.STATUS_HAVE_MORE : LoadMoreAdapter.STATUS_LOADED_ALL); + adapter.notifyDataSetChanged(); + } + + @Override + public void setPresenter(HomeContract.Presenter presenter) { + this.presenter = presenter; + } + + @Override + public boolean isActive() { + return isAdded(); + } + + @Override + public void showProgress() { + srl.post(new Runnable() { + @Override + public void run() { + srl.setRefreshing(true); + } + }); + } + + @Override + public void dismissProgress() { + srl.setRefreshing(false); + } + + @Override + public void showTip(String message) { + showToast(message); + } + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/home/HomePresenter.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/home/HomePresenter.java new file mode 100644 index 0000000..7acdf92 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/home/HomePresenter.java @@ -0,0 +1,75 @@ +package com.boredream.designrescollection.ui.home; + +import com.boredream.bdcodehelper.entity.ListResponse; +import com.boredream.bdcodehelper.net.ObservableDecorator; +import com.boredream.bdcodehelper.utils.ErrorInfoUtils; +import com.boredream.designrescollection.constants.CommonConstants; +import com.boredream.designrescollection.entity.DesignRes; +import com.boredream.designrescollection.net.ApiService; + +import java.util.List; + +import rx.Observable; +import rx.Subscriber; + +public class HomePresenter implements HomeContract.Presenter { + + private final HomeContract.View view; + private final ApiService service; + public List datas; + + public HomePresenter(HomeContract.View view, ApiService service) { + this.view = view; + this.service = service; + this.view.setPresenter(this); + } + + @Override + public void pullToLoadList() { + loadData(1); + } + + @Override + public void loadList(final int page) { + if(page == 1) { + view.showProgress(); + } + + loadData(page); + } + + private void loadData(final int page) { + Observable> observable = service.getDesignRes( + CommonConstants.COUNT_OF_PAGE, (page - 1) * CommonConstants.COUNT_OF_PAGE); + ObservableDecorator.decorate(observable).subscribe( + new Subscriber>() { + @Override + public void onCompleted() { + + } + + @Override + public void onError(Throwable e) { + if (!view.isActive()) { + return; + } + view.dismissProgress(); + + String error = ErrorInfoUtils.parseHttpErrorInfo(e); + view.showTip(error); + } + + @Override + public void onNext(ListResponse response) { + if (!view.isActive()) { + return; + } + view.dismissProgress(); + + datas = response.getResults(); + view.loadListSuccess(page, datas); + } + }); + } + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginActivity.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginActivity.java new file mode 100644 index 0000000..e553993 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginActivity.java @@ -0,0 +1,48 @@ +package com.boredream.designrescollection.ui.login; + + +import android.os.Bundle; + +import com.boredream.bdcodehelper.utils.ActivityUtils; +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.base.BaseActivity; + +import javax.inject.Inject; + +public class LoginActivity extends BaseActivity { + + /** + * 是否为验证登录,true-登录成功后,直接finish返回到来源页 false-登录成功后跳转到主页 + */ + private boolean checkLogin; + + @Inject LoginPresenter presenter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + + initExtras(); + initView(); + } + + private void initExtras() { + checkLogin = getIntent().getBooleanExtra("checkLogin", false); + } + + private void initView() { + initBackTitle("登录"); + + LoginFragment loginFragment = (LoginFragment) getSupportFragmentManager().findFragmentById(R.id.fl_content); + if (loginFragment == null) { + loginFragment = LoginFragment.newInstance(checkLogin); + ActivityUtils.addFragmentToActivity(getSupportFragmentManager(), loginFragment, R.id.fl_content); + } + + DaggerLoginComponent.builder() + .loginPresenterModule(new LoginPresenterModule(loginFragment)) + .build() + .inject(this); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginComponent.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginComponent.java new file mode 100644 index 0000000..3ed63ad --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginComponent.java @@ -0,0 +1,11 @@ +package com.boredream.designrescollection.ui.login; + +import com.boredream.designrescollection.utils.PerActivity; + +import dagger.Component; + +@PerActivity +@Component(modules = {LoginPresenterModule.class}) +public interface LoginComponent { + void inject(LoginActivity activity); +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginContract.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginContract.java new file mode 100644 index 0000000..00c88dc --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginContract.java @@ -0,0 +1,23 @@ +package com.boredream.designrescollection.ui.login; + +import com.boredream.designrescollection.base.BasePresenter; +import com.boredream.designrescollection.base.BaseView; +import com.boredream.designrescollection.entity.User; + +/** + * This specifies the contract between the view and the presenter. + */ +public interface LoginContract { + + interface View extends BaseView { + + void loginSuccess(User user); + + } + + interface Presenter extends BasePresenter { + + void login(String username, String password); + + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginFragment.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginFragment.java new file mode 100644 index 0000000..b391e86 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginFragment.java @@ -0,0 +1,123 @@ +package com.boredream.designrescollection.ui.login; + +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.base.BaseFragment; +import com.boredream.designrescollection.entity.User; +import com.boredream.designrescollection.ui.MainActivity; +import com.boredream.designrescollection.ui.register.RegisterStep1Activity; +import com.boredream.designrescollection.utils.UserInfoKeeper; + +public class LoginFragment extends BaseFragment implements LoginContract.View, View.OnClickListener { + + private static final String ARGUMENT_CHECK_LOGIN = "checkLogin"; + private boolean checkLogin; + + private LoginContract.Presenter presenter; + + private EditText et_username; + private EditText et_password; + private TextView tv_forget_psw; + private Button btn_login; + private LinearLayout ll_regist; + + public static LoginFragment newInstance(boolean checkLogin) { + Bundle arguments = new Bundle(); + arguments.putBoolean(ARGUMENT_CHECK_LOGIN, checkLogin); + LoginFragment fragment = new LoginFragment(); + fragment.setArguments(arguments); + return fragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = View.inflate(activity, R.layout.frag_login, null); + initExtras(); + initView(view); + return view; + } + + private void initExtras() { + checkLogin = getArguments().getBoolean(ARGUMENT_CHECK_LOGIN); + } + + private void initView(View view) { + et_username = (EditText) view.findViewById(R.id.et_username); + et_password = (EditText) view.findViewById(R.id.et_password); + tv_forget_psw = (TextView) view.findViewById(R.id.tv_forget_psw); + btn_login = (Button) view.findViewById(R.id.btn_login); + ll_regist = (LinearLayout) view.findViewById(R.id.ll_regist); + + tv_forget_psw.setOnClickListener(this); + btn_login.setOnClickListener(this); + ll_regist.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + Intent intent = new Intent(activity, RegisterStep1Activity.class); + switch (v.getId()) { + case R.id.btn_login: + String username = et_username.getText().toString().trim(); + String password = et_password.getText().toString().trim(); + presenter.login(username, password); + break; + case R.id.tv_forget_psw: + intent.putExtra("type", 1); + startActivity(intent); + break; + case R.id.ll_regist: + intent.putExtra("type", 0); + startActivity(intent); + break; + } + } + + @Override + public void showProgress() { + showProgressDialog(); + } + + @Override + public void dismissProgress() { + dismissProgressDialog(); + } + + @Override + public void loginSuccess(User user) { + dismissProgressDialog(); + + UserInfoKeeper.setCurrentUser(user); + + if (checkLogin) { + activity.finish(); + } else { + intent2Activity(MainActivity.class); + } + } + + @Override + public void showTip(String message) { + showToast(message); + } + + @Override + public boolean isActive() { + return isAdded(); + } + + @Override + public void setPresenter(LoginContract.Presenter presenter) { + this.presenter = presenter; + } + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginPresenter.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginPresenter.java new file mode 100644 index 0000000..d85cced --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginPresenter.java @@ -0,0 +1,69 @@ +package com.boredream.designrescollection.ui.login; + +import com.boredream.bdcodehelper.net.ObservableDecorator; +import com.boredream.bdcodehelper.utils.ErrorInfoUtils; +import com.boredream.bdcodehelper.utils.StringUtils; +import com.boredream.designrescollection.entity.User; +import com.boredream.designrescollection.net.ApiService; + +import javax.inject.Inject; + +import rx.Observable; +import rx.Subscriber; + +public class LoginPresenter implements LoginContract.Presenter { + + private final LoginContract.View view; + private final ApiService service; + + @Inject + public LoginPresenter(LoginContract.View view, ApiService service) { + this.view = view; + this.service = service; + this.view.setPresenter(this); + } + + @Override + public void login(String username, String password) { + if (StringUtils.isEmpty(username)) { + view.showTip("用户名不能为空"); + return; + } + + if (StringUtils.isEmpty(password)) { + view.showTip("密码不能为空"); + return; + } + + view.showProgress(); + + Observable observable = service.login(username, password); + ObservableDecorator.decorate(observable).subscribe(new Subscriber() { + @Override + public void onCompleted() { + + } + + @Override + public void onError(Throwable e) { + if (!view.isActive()) { + return; + } + view.dismissProgress(); + + String error = ErrorInfoUtils.parseHttpErrorInfo(e); + view.showTip(error); + } + + @Override + public void onNext(User user) { + if (!view.isActive()) { + return; + } + view.dismissProgress(); + + view.loginSuccess(user); + } + }); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginPresenterModule.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginPresenterModule.java new file mode 100644 index 0000000..92d9dd0 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/login/LoginPresenterModule.java @@ -0,0 +1,20 @@ +package com.boredream.designrescollection.ui.login; + +import dagger.Module; +import dagger.Provides; + +@Module +public class LoginPresenterModule { + + private final LoginContract.View mView; + + public LoginPresenterModule(LoginContract.View view) { + mView = view; + } + + @Provides + LoginContract.View provideLoginContractView() { + return mView; + } + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/modifytext/ModifyTextActivity.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/modifytext/ModifyTextActivity.java new file mode 100644 index 0000000..2f6fa3f --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/modifytext/ModifyTextActivity.java @@ -0,0 +1,110 @@ +package com.boredream.designrescollection.ui.modifytext; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.EditText; + +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.base.BaseActivity; + +/** + * 修改文字内容输入框页面 + */ +public class ModifyTextActivity extends BaseActivity implements ModifyTextContract.View { + + public static final String EXTRA_TITLE = "title"; + public static final String EXTRA_OLD_STRING = "oldString"; + + public static final String RESULT_IS_MODIFY = "isModify"; + public static final String RESULT_NEW_STRING = "newString"; + + private String title; + private String oldString; + + private ModifyTextContract.Presenter presenter; + private EditText et_input; + + public static void start(Activity context, int requestCode, String title, String oldString) { + Intent intent = new Intent(context, ModifyTextActivity.class); + intent.putExtra(ModifyTextActivity.EXTRA_TITLE, title); + intent.putExtra(ModifyTextActivity.EXTRA_OLD_STRING, oldString); + context.startActivityForResult(intent, requestCode); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_input); + + initExtras(); + initView(); + initData(); + } + + private void initExtras() { + Intent intent = getIntent(); + title = intent.getStringExtra(EXTRA_TITLE); + oldString = intent.getStringExtra(EXTRA_OLD_STRING); + } + + private void initView() { + presenter = new ModifyTextPresenter(this); + + initBackTitle(title + "修改") + .setRightText("保存") + .setRightOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + submit(); + } + }); + et_input = (EditText) findViewById(R.id.et_input); + } + + private void initData() { + if (oldString != null) { + et_input.setText(oldString); + } + } + + private void submit() { + String str = et_input.getText().toString().trim(); + presenter.modifyText(title, oldString, str); + } + + @Override + public void modifyTextSuccess(boolean isModify, String newString) { + Intent intent = new Intent(); + intent.putExtra(RESULT_NEW_STRING, newString); + intent.putExtra(RESULT_IS_MODIFY, isModify); + setResult(RESULT_OK, intent); + finish(); + } + + @Override + public void setPresenter(ModifyTextContract.Presenter presenter) { + this.presenter = presenter; + } + + @Override + public boolean isActive() { + return isActive; + } + + @Override + public void showProgress() { + + } + + @Override + public void dismissProgress() { + + } + + @Override + public void showTip(String message) { + showToast(message); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/modifytext/ModifyTextContract.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/modifytext/ModifyTextContract.java new file mode 100644 index 0000000..74466d4 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/modifytext/ModifyTextContract.java @@ -0,0 +1,19 @@ +package com.boredream.designrescollection.ui.modifytext; + +import com.boredream.designrescollection.base.BasePresenter; +import com.boredream.designrescollection.base.BaseView; + +public interface ModifyTextContract { + + interface View extends BaseView { + + void modifyTextSuccess(boolean isModify, String newString); + + } + + interface Presenter extends BasePresenter { + + void modifyText(String title, String oldString, String modifyString); + + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/modifytext/ModifyTextPresenter.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/modifytext/ModifyTextPresenter.java new file mode 100644 index 0000000..d66bca7 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/modifytext/ModifyTextPresenter.java @@ -0,0 +1,25 @@ +package com.boredream.designrescollection.ui.modifytext; + +import com.boredream.bdcodehelper.utils.StringUtils; + +public class ModifyTextPresenter implements ModifyTextContract.Presenter { + + private final ModifyTextContract.View view; + + public ModifyTextPresenter(ModifyTextContract.View view) { + this.view = view; + this.view.setPresenter(this); + } + + @Override + public void modifyText(String title, String oldString, String modifyString) { + if (StringUtils.isEmpty(modifyString)) { + view.showTip(title + "不能为空"); + return; + } + + // 旧文字为空或旧文字和新文字不相等,视为已修改 + boolean isModify = oldString == null || !oldString.equals(modifyString); + view.modifyTextSuccess(isModify, modifyString); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterContract.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterContract.java new file mode 100644 index 0000000..d3296be --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterContract.java @@ -0,0 +1,21 @@ +package com.boredream.designrescollection.ui.register; + +import com.boredream.designrescollection.base.BasePresenter; +import com.boredream.designrescollection.base.BaseView; +import com.boredream.designrescollection.entity.User; + +public class RegisterContract { + interface View extends BaseView { + + void requestSmsSuccess(String phone, String password); + + void registerSuccess(User user); + } + + interface Presenter extends BasePresenter { + + void requestSms(String phone, String password); + + void register(String phone, String password, String code); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterPresenter.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterPresenter.java new file mode 100644 index 0000000..c8df0ed --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterPresenter.java @@ -0,0 +1,118 @@ +package com.boredream.designrescollection.ui.register; + +import com.boredream.bdcodehelper.net.ObservableDecorator; +import com.boredream.bdcodehelper.utils.ErrorInfoUtils; +import com.boredream.bdcodehelper.utils.StringUtils; +import com.boredream.designrescollection.entity.User; +import com.boredream.designrescollection.net.ApiService; +import com.boredream.designrescollection.utils.UserInfoKeeper; + +import rx.Observable; +import rx.Subscriber; + +public class RegisterPresenter implements RegisterContract.Presenter { + + private RegisterContract.View view; + private ApiService service; + + public RegisterPresenter(RegisterContract.View view, ApiService service) { + this.view = view; + this.service = service; + this.view.setPresenter(this); + } + + @Override + public void requestSms(final String phone, final String password) { + if (StringUtils.isEmpty(phone)) { + view.showTip("请输入用户名"); + return; + } + + if (StringUtils.isEmpty(password) || password.length() < 6) { + view.showTip("请设置登录密码,不少于6位"); + return; + } + + view.showProgress(); + + // FIXME 模拟获取短信接口 + Observable observable = Observable.just("发送验证码咯~"); + ObservableDecorator.decorate(observable).subscribe(new Subscriber() { + @Override + public void onCompleted() { + + } + + @Override + public void onError(Throwable e) { + if (!view.isActive()) { + return; + } + view.dismissProgress(); + + String error = ErrorInfoUtils.parseHttpErrorInfo(e); + view.showTip(error); + } + + @Override + public void onNext(String string) { + if (!view.isActive()) { + return; + } + view.dismissProgress(); + + view.requestSmsSuccess(phone, password); + } + }); + } + + @Override + public void register(String phone, String password, String code) { + if (StringUtils.isEmpty(code)) { + view.showTip("请输入验证码"); + return; + } + + view.showProgress(); + + // 注册接口 + User user = new User(); + user.setMobilePhoneNumber(phone); + user.setUsername(phone); + user.setPassword(password); + user.setSmsCode(code); + Observable observable = service.register(user); + ObservableDecorator.decorate(observable).subscribe(new Subscriber() { + @Override + public void onCompleted() { + + } + + @Override + public void onError(Throwable e) { + if (!view.isActive()) { + return; + } + + view.dismissProgress(); + + String error = ErrorInfoUtils.parseHttpErrorInfo(e); + view.showTip(error); + } + + @Override + public void onNext(User user) { + UserInfoKeeper.setCurrentUser(user); + + if (!view.isActive()) { + return; + } + + view.dismissProgress(); + + view.registerSuccess(user); + } + }); + } + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterStep1Activity.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterStep1Activity.java new file mode 100644 index 0000000..6f3c0aa --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterStep1Activity.java @@ -0,0 +1,102 @@ +package com.boredream.designrescollection.ui.register; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; + +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.base.BaseActivity; +import com.boredream.designrescollection.entity.User; +import com.boredream.designrescollection.net.ApiService; + +import javax.inject.Inject; + +/** + * 注册页面步骤一 + */ +public class RegisterStep1Activity extends BaseActivity implements View.OnClickListener, RegisterContract.View { + + private RegisterContract.Presenter presenter; + @Inject ApiService service; + + private EditText et_username; + private EditText et_password; + private Button btn_next; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_register_step1); + + initView(); + } + + private void initView() { + presenter = new RegisterPresenter(this, service); + initBackTitle("注册"); + + et_username = (EditText) findViewById(R.id.et_username); + et_password = (EditText) findViewById(R.id.et_password); + btn_next = (Button) findViewById(R.id.btn_next); + + btn_next.setOnClickListener(this); + } + + private void next() { + String phone = et_username.getText().toString().trim(); + String password = et_password.getText().toString().trim(); + + presenter.requestSms(phone, password); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_next: + next(); + break; + } + } + + @Override + public void requestSmsSuccess(String phone, String password) { + // 短信验证码发送成功后,跳转到短信验证页,同时传递所需数据 + Intent intent = new Intent(this, RegisterStep2Activity.class); + intent.putExtra("phone", phone); + intent.putExtra("password", password); + startActivity(intent); + } + + @Override + public void registerSuccess(User user) { + // do nothing + } + + @Override + public void setPresenter(RegisterContract.Presenter presenter) { + this.presenter = presenter; + } + + @Override + public boolean isActive() { + return isActive; + } + + @Override + public void showProgress() { + showProgressDialog(); + } + + @Override + public void dismissProgress() { + dismissProgressDialog(); + } + + @Override + public void showTip(String message) { + showToast(message); + } + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterStep2Activity.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterStep2Activity.java new file mode 100644 index 0000000..b290d16 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterStep2Activity.java @@ -0,0 +1,168 @@ +package com.boredream.designrescollection.ui.register; + + +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.support.v7.app.AlertDialog; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; + +import com.boredream.bdcodehelper.utils.DateUtils; +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.base.BaseActivity; +import com.boredream.designrescollection.entity.User; +import com.boredream.designrescollection.net.ApiService; +import com.boredream.designrescollection.ui.MainActivity; + +import javax.inject.Inject; + +/** + * 注册页面步骤二 + */ +public class RegisterStep2Activity extends BaseActivity implements View.OnClickListener, RegisterContract.View { + + // 总倒计时60秒 + private static final long TOTCAL_TIME = 60 * DateUtils.ONE_SECOND_MILLIONS; + // 每次减少1秒 + private static final long COUNT_DOWN_INTERVAL = DateUtils.ONE_SECOND_MILLIONS; + + private RegisterContract.Presenter presenter; + @Inject ApiService service; + + private EditText et_verification_code; + private Button btn_code_info; + private Button btn_next; + + private String phone; + private String password; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_register_step2); + + initExtras(); + initView(); + initData(); + } + + private void initExtras() { + Intent intent = getIntent(); + phone = intent.getStringExtra("phone"); + password = intent.getStringExtra("password"); + } + + private void initView() { + presenter = new RegisterPresenter(this, service); + initBackTitle("手机号验证"); + + et_verification_code = (EditText) findViewById(R.id.et_verification_code); + btn_code_info = (Button) findViewById(R.id.btn_code_info); + btn_next = (Button) findViewById(R.id.btn_next); + + btn_code_info.setOnClickListener(this); + btn_next.setOnClickListener(this); + } + + private void initData() { + startCountDown(); + } + + /** + * 开始倒计时 + */ + private void startCountDown() { + showToast("短信验证码发送成功"); + + btn_code_info.setText("60秒"); + btn_code_info.setEnabled(false); + + // 倒计时开始,共60秒,每次减少1秒 + CountDownTimer timer = new CountDownTimer(TOTCAL_TIME, COUNT_DOWN_INTERVAL) { + @Override + public void onTick(long l) { + // 重新获取(60) + String restTime = (int) (l / COUNT_DOWN_INTERVAL) + "秒"; + btn_code_info.setText(restTime); + } + + @Override + public void onFinish() { + // 倒计时结束,重置按钮 + btn_code_info.setText("重新获取"); + btn_code_info.setEnabled(true); + } + }; + timer.start(); + } + + /** + * 根据类型提交注册或重置密码接口 + */ + private void submit() { + String code = et_verification_code.getText().toString().trim(); + presenter.register(phone, password, code); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_code_info: + presenter.requestSms(phone, password); + break; + case R.id.btn_next: + submit(); + break; + } + } + + @Override + public void requestSmsSuccess(String phone, String password) { + startCountDown(); + } + + @Override + public void registerSuccess(User user) { + // 注册成功提示框,提醒用户完善资料 + new AlertDialog.Builder(this) + .setMessage("注册成功,你可以在个人详情中修改或完善用户信息。") + .setPositiveButton("确定", null) + .setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + // 确定或者返回键关闭对话框都走此 + intent2Activity(MainActivity.class); + } + }) + .setCancelable(false) // cancelable设为false,防止用户点击返回键关闭对话框停留在当前页面 + .show(); + } + + @Override + public void setPresenter(RegisterContract.Presenter presenter) { + this.presenter = presenter; + } + + @Override + public boolean isActive() { + return isActive; + } + + @Override + public void showProgress() { + showProgressDialog(); + } + + @Override + public void dismissProgress() { + dismissProgressDialog(); + } + + @Override + public void showTip(String message) { + showToast(message); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/userinfoedit/UserInfoEditActivity.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/userinfoedit/UserInfoEditActivity.java new file mode 100644 index 0000000..b5ed3db --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/userinfoedit/UserInfoEditActivity.java @@ -0,0 +1,166 @@ +package com.boredream.designrescollection.ui.userinfoedit; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.boredream.bdcodehelper.net.ObservableDecorator; +import com.boredream.bdcodehelper.utils.ImageUtils; +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.base.BaseActivity; +import com.boredream.designrescollection.entity.User; +import com.boredream.designrescollection.net.ApiService; +import com.boredream.designrescollection.net.GlideHelper; +import com.boredream.designrescollection.ui.modifytext.ModifyTextActivity; +import com.boredream.designrescollection.utils.UserInfoKeeper; + +import javax.inject.Inject; + +import rx.Observable; +import rx.Subscriber; + +public class UserInfoEditActivity extends BaseActivity implements View.OnClickListener, UserInfoEditContract.View { + + private static final int REQUEST_CODE_MODIFY_NICKNAME = 110; + + private UserInfoEditContract.Presenter presenter; + @Inject ApiService service; + + private ImageView iv_avatar; + private LinearLayout ll_avatar; + private TextView tv_username; + private LinearLayout ll_username; + + private User currentUser; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_user_info_edit); + + initView(); + initData(); + } + + private void initData() { + currentUser = UserInfoKeeper.getCurrentUser(); + GlideHelper.showAvatar(this, currentUser.getAvatar(), iv_avatar); + tv_username.setText(currentUser.getNickname()); + } + + private void initView() { + presenter = new UserInfoEditPresenter(this, service, UserInfoKeeper.getCurrentUser()); + + initBackTitle("修改个人资料"); + + iv_avatar = (ImageView) findViewById(R.id.iv_avatar); + ll_avatar = (LinearLayout) findViewById(R.id.ll_avatar); + tv_username = (TextView) findViewById(R.id.tv_username); + ll_username = (LinearLayout) findViewById(R.id.ll_username); + + ll_avatar.setOnClickListener(this); + ll_username.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.ll_avatar: + ImageUtils.showImagePickDialog(this); + break; + case R.id.ll_username: + ModifyTextActivity.start(this, REQUEST_CODE_MODIFY_NICKNAME, + "昵称", currentUser.getNickname()); + break; + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (resultCode != RESULT_OK) { + return; + } + + Uri uri; + switch (requestCode) { + case ImageUtils.REQUEST_CODE_FROM_ALBUM: + // 从相册选择 + uri = data.getData(); + compressAndUpload(uri); + break; + case ImageUtils.REQUEST_CODE_FROM_CAMERA: + // 相机拍照 + uri = ImageUtils.imageUriFromCamera; + compressAndUpload(uri); + break; + case REQUEST_CODE_MODIFY_NICKNAME: + boolean isModify = data.getBooleanExtra(ModifyTextActivity.RESULT_IS_MODIFY, true); + if (!isModify) { + // 未修改,不做任何操作 + return; + } + presenter.updateNickname(data.getStringExtra(ModifyTextActivity.RESULT_NEW_STRING)); + break; + } + } + + private void compressAndUpload(final Uri uri) { + showProgress(); + + Observable observable = ImageUtils.compressImage(this, uri, iv_avatar.getWidth(), iv_avatar.getHeight()); + ObservableDecorator.decorate(observable) + .subscribe(new Subscriber() { + @Override + public void onCompleted() { + + } + + @Override + public void onError(Throwable e) { + showToast(e.getMessage()); + dismissProgress(); + } + + @Override + public void onNext(byte[] bytes) { + presenter.uploadAvatar(bytes); + } + }); + } + + @Override + public void uploadUserInfoSuccess() { + initData(); + } + + @Override + public void setPresenter(UserInfoEditContract.Presenter presenter) { + this.presenter = presenter; + } + + @Override + public boolean isActive() { + return isActive; + } + + @Override + public void showProgress() { + showProgressDialog(); + } + + @Override + public void dismissProgress() { + dismissProgressDialog(); + } + + @Override + public void showTip(String message) { + showToast(message); + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/userinfoedit/UserInfoEditContract.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/userinfoedit/UserInfoEditContract.java new file mode 100644 index 0000000..d28be5c --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/userinfoedit/UserInfoEditContract.java @@ -0,0 +1,27 @@ +package com.boredream.designrescollection.ui.userinfoedit; + +import com.boredream.designrescollection.base.BasePresenter; +import com.boredream.designrescollection.base.BaseView; + +public interface UserInfoEditContract { + + interface View extends BaseView { + + void uploadUserInfoSuccess(); + + } + + interface Presenter extends BasePresenter { + + /** + * 上传用户头像 + */ + void uploadAvatar(byte[] bytes); + + /** + * 修改昵称 + */ + void updateNickname(String nickname); + + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/userinfoedit/UserInfoEditPresenter.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/userinfoedit/UserInfoEditPresenter.java new file mode 100644 index 0000000..cab999d --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/ui/userinfoedit/UserInfoEditPresenter.java @@ -0,0 +1,140 @@ +package com.boredream.designrescollection.ui.userinfoedit; + +import com.boredream.bdcodehelper.entity.FileUploadResponse; +import com.boredream.bdcodehelper.net.ObservableDecorator; +import com.boredream.bdcodehelper.utils.ErrorInfoUtils; +import com.boredream.bdcodehelper.utils.StringUtils; +import com.boredream.designrescollection.base.BaseEntity; +import com.boredream.designrescollection.entity.User; +import com.boredream.designrescollection.net.ApiService; +import com.squareup.okhttp.MediaType; +import com.squareup.okhttp.RequestBody; + +import java.util.HashMap; +import java.util.Map; + +import rx.Observable; +import rx.Subscriber; + +public class UserInfoEditPresenter implements UserInfoEditContract.Presenter { + + private final UserInfoEditContract.View view; + private final ApiService service; + private final User user; + + public UserInfoEditPresenter(UserInfoEditContract.View view, + ApiService service, + User user) { + this.view = view; + this.service = service; + this.user = user; + this.view.setPresenter(this); + } + + @Override + public void uploadAvatar(byte[] bytes) { + // 第一步,上传头像文件到服务器 + String filename = "image_" + System.currentTimeMillis() + ".jpg"; + RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpeg"), bytes); + Observable observable = service.fileUpload(filename, requestBody); + ObservableDecorator.decorate(observable).subscribe( + new Subscriber() { + @Override + public void onCompleted() { + + } + + @Override + public void onNext(FileUploadResponse fileUploadResponse) { + // 第二步,将上传图片返回的url地址更新至用户对象中 + updateUserAvatar(/*HttpRequest.FILE_HOST + */fileUploadResponse.getUrl()); + } + + @Override + public void onError(Throwable throwable) { + view.dismissProgress(); + } + }); + } + + /** + * 更新用户头像 + * + * @param avatarUrl 头像图片地址 + */ + public void updateUserAvatar(final String avatarUrl) { + Map updateMap = new HashMap(); + updateMap.put("avatar", avatarUrl); + + Observable observable = service.updateUserById( + user.getObjectId(), updateMap); + ObservableDecorator.decorate(observable) + .subscribe(new Subscriber() { + @Override + public void onCompleted() { + + } + + @Override + public void onNext(BaseEntity entity) { + view.dismissProgress(); + + // 成功后更新当前用户的头像数据 + user.setAvatar(avatarUrl); + + view.uploadUserInfoSuccess(); + + view.showTip("上传修改头像成功"); + } + + @Override + public void onError(Throwable throwable) { + view.dismissProgress(); + + view.showTip("上传修改头像失败"); + } + }); + } + + @Override + public void updateNickname(final String nickname) { + // validate + if (StringUtils.isEmpty(nickname)) { + view.showTip("昵称不能为空"); + return; + } + + view.showProgress(); + + Map updateMap = new HashMap(); + updateMap.put("nickname", nickname); + Observable observable = service.updateUserById(user.getObjectId(), updateMap); + ObservableDecorator.decorate(observable) + .subscribe(new Subscriber() { + @Override + public void onCompleted() { + + } + + @Override + public void onNext(BaseEntity entity) { + view.dismissProgress(); + + // 修改成功后更新当前用户的昵称 + user.setNickname(nickname); + + view.showTip("昵称修改成功"); + view.uploadUserInfoSuccess(); + } + + @Override + public void onError(Throwable throwable) { + view.dismissProgress(); + + String error = ErrorInfoUtils.parseHttpErrorInfo(throwable); + view.showTip(error); + } + }); + } + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/utils/PerActivity.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/utils/PerActivity.java new file mode 100644 index 0000000..53f83b8 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/utils/PerActivity.java @@ -0,0 +1,13 @@ +package com.boredream.designrescollection.utils; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Scope; + +@Documented +@Scope +@Retention(RetentionPolicy.RUNTIME) +public @interface PerActivity { +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/utils/PerApplication.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/utils/PerApplication.java new file mode 100644 index 0000000..101ea44 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/utils/PerApplication.java @@ -0,0 +1,13 @@ +package com.boredream.designrescollection.utils; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Scope; + +@Documented +@Scope +@Retention(RetentionPolicy.RUNTIME) +public @interface PerApplication { +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/utils/UpdateUtils.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/utils/UpdateUtils.java new file mode 100644 index 0000000..912215d --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/utils/UpdateUtils.java @@ -0,0 +1,272 @@ +package com.boredream.designrescollection.utils; + + +import android.app.Activity; +import android.app.DownloadManager; +import android.content.Context; +import android.content.DialogInterface; +import android.database.Cursor; +import android.net.Uri; +import android.os.Environment; +import android.support.annotation.NonNull; +import android.support.v7.app.AlertDialog; + +import com.boredream.bdcodehelper.entity.AppUpdateInfo; +import com.boredream.bdcodehelper.entity.ListResponse; +import com.boredream.bdcodehelper.net.ObservableDecorator; +import com.boredream.bdcodehelper.utils.AppUtils; +import com.boredream.bdcodehelper.utils.DialogUtils; +import com.boredream.bdcodehelper.utils.NetUtils; +import com.boredream.bdcodehelper.utils.ToastUtils; +import com.boredream.designrescollection.R; +import com.boredream.designrescollection.base.BaseActivity; +import com.boredream.designrescollection.net.SimpleSubscriber; + +import java.util.ArrayList; +import java.util.Locale; + +import rx.Observable; + +/** + * 检查更新工具类 + *

+ * 可以注册下载完成广播,在其中进行提示跳转安装等行为 + *

+ *

  • 注册广播
  • + *
    + * context.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    + * 
    + *

    + *

  • 使用广播
  • + *
    + * String action = intent.getAction();
    + * if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
    + * long enqueueId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
    + * Uri uri = UpdateUtils.getDownloadUriById(context, enqueueId);
    + * // do something
    + * }
    + * 
    + *

    + */ +public class UpdateUtils { + + public static final int DOWNLOAD_STATUS_NEED_LOAD = 1; + public static final int DOWNLOAD_STATUS_RUNNING = 2; + public static final int DOWNLOAD_STATUS_LOADED = 3; + + /** + * 检测版本更新 + * + * @param context + * @param isForceCheck 是否强制检测更新 + * true强制 - 无论什么网络环境都会提示更新 + * false非强制 - WiFi情况下才提示更新 + */ + public static void checkUpdate(final BaseActivity context, + Observable> observable, + final boolean isForceCheck) { + if (!NetUtils.isConnected(context)) { + // 无网络时 + if (isForceCheck) { + // 手动强制检测更新时,提示文字 + ToastUtils.showToast(context, "请检查网络连接"); + } else { + // 非强制不做操作 + } + return; + } + + // 开始检测更新 + + if (isForceCheck) { + // 强制更新时,才提示进度框 + context.showProgressDialog(); + } + + ObservableDecorator.decorate(observable).subscribe( + new SimpleSubscriber>(context) { + @Override + public void onError(Throwable throwable) { + if (isForceCheck) { + // 强制更新时,才提示错误 + super.onError(throwable); + } + context.dismissProgressDialog(); + } + + @Override + public void onNext(ListResponse response) { + context.dismissProgressDialog(); + + ArrayList results = response.getResults(); + if (results.size() == 0) { + if (isForceCheck) { + ToastUtils.showToast(context, "当前已经是最新版本"); + } + } + + + AppUpdateInfo newestUpdateInfo = results.get(0); + for (AppUpdateInfo updateInfo : results) { + if (updateInfo.getVersion()> newestUpdateInfo.getVersion()) { + // 取最大版本号的作为最新版本 + newestUpdateInfo = updateInfo; + } + } + + if (newestUpdateInfo.getVersion() <= AppUtils.getAppVersionCode(context)) { + if (isForceCheck) { + ToastUtils.showToast(context, "当前已经是最新版本"); + } + } else { + showUpdateConfirmDialog(context, newestUpdateInfo); + } + } + } + ); + } + + /** + * 无Wifi状态确认更新对话框 + */ + private static void showNoWifiConfirmDialog(final BaseActivity context, final AppUpdateInfo updateInfo) { + DialogUtils.showCommonDialog(context, "没有wifi连接,是否继续选择更新?", + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + startDownload(context, updateInfo); + } + }); + } + + /** + * 显示更新对话框,包含版本相关信息 + */ + private static void showUpdateConfirmDialog(final BaseActivity context, final AppUpdateInfo updateInfo) { + String content = String.format(Locale.CHINESE, + context.getResources().getString(R.string.update_info), + updateInfo.getVersionName(), + updateInfo.getUpdateInfo() == null ? "无" : updateInfo.getUpdateInfo()); + + new AlertDialog.Builder(context) + .setTitle("发现新版本") + .setMessage(content) + .setPositiveButton("立即更新", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (NetUtils.isWifi(context)) { + startDownload(context, updateInfo); + } else { + showNoWifiConfirmDialog(context, updateInfo); + } + } + }) + .setNegativeButton("以后再说", null) + .show(); + } + + /** + * 开始下载 + * + * @param context + * @param updateInfo + */ + private static void startDownload(BaseActivity context, AppUpdateInfo updateInfo) { + int status = getDownloadStatus(context, updateInfo); + if (status != DOWNLOAD_STATUS_NEED_LOAD) { + // 不用下载则无需下列操作 + return; + } + + ToastUtils.showToast(context, "开始下载安装包..."); + + // parse url + Uri mUri = Uri.parse(updateInfo.getFileUrl()); + + // create request + DownloadManager.Request r = new DownloadManager.Request(mUri); + + // set request property + String apkName = getDownloadApkName(context, updateInfo); + r.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkName); + r.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); + + // create manager + DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); + + // key code, set mine type + r.setMimeType("application/vnd.android.package-archive"); + + // add to queue + dm.enqueue(r); + } + + @NonNull + private static String getDownloadApkName(BaseActivity context, AppUpdateInfo updateInfo) { + return context.getString(R.string.app_name) + "_" + updateInfo.getVersionName() + ".apk"; + } + + /** + * 判断当前版本文件下载状态 + * + * @param context + * @param updateInfo + * @return + */ + private static int getDownloadStatus(BaseActivity context, AppUpdateInfo updateInfo) { + DownloadManager.Query query = new DownloadManager.Query(); + DownloadManager dm = (DownloadManager) context.getSystemService(Activity.DOWNLOAD_SERVICE); + Cursor c = dm.query(query); + + if (!c.moveToFirst()) { + // 无下载内容 + return DOWNLOAD_STATUS_NEED_LOAD; + } + + do { + int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)); + String title = c.getString(c.getColumnIndex(DownloadManager.COLUMN_TITLE)); + String apkName = getDownloadApkName(context, updateInfo); + if (title.equals(apkName)) { + // 如果下载列表中文件是当前版本应用,则继续判断下载状态 + if (status == DownloadManager.STATUS_SUCCESSFUL) { + // 如果已经下载,返回状态,同时直接提示安装 + String uri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); + AppUtils.promptInstall(context, Uri.parse(uri)); + return DOWNLOAD_STATUS_LOADED; + } else if (status == DownloadManager.STATUS_RUNNING + || status == DownloadManager.STATUS_PAUSED + || status == DownloadManager.STATUS_PENDING) { + return DOWNLOAD_STATUS_RUNNING; + } else { + // 失败也视为可以再次下载 + return DOWNLOAD_STATUS_NEED_LOAD; + } + } + } while (c.moveToNext()); + + return DOWNLOAD_STATUS_NEED_LOAD; + } + + /** + * 根据下载队列id获取下载Uri + * + * @param enqueueId + * @return null-获取不到 + */ + public static Uri getDownloadUriById(Context context, long enqueueId) { + DownloadManager.Query query = new DownloadManager.Query(); + query.setFilterById(enqueueId); + DownloadManager dm = (DownloadManager) context.getSystemService(Activity.DOWNLOAD_SERVICE); + Cursor c = dm.query(query); + if (c.moveToFirst()) { + int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS); + if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) { + String uri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); + return Uri.parse(uri); + } + } + return null; + } + +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/utils/UserInfoKeeper.java b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/utils/UserInfoKeeper.java new file mode 100644 index 0000000..18b6764 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/java/com/boredream/designrescollection/utils/UserInfoKeeper.java @@ -0,0 +1,68 @@ +package com.boredream.designrescollection.utils; + + +import android.content.Context; +import android.content.Intent; + +import com.boredream.designrescollection.entity.User; +import com.boredream.designrescollection.ui.login.LoginActivity; + +/** + * 用户信息保存工具 + */ +public class UserInfoKeeper { + + private static User currentUser; + + /** + * 获取当前登录用户 + */ + public static User getCurrentUser() { + return currentUser; + } + + /** + * 保存设置当前登录用户 + */ + public static void setCurrentUser(User user) { + currentUser = user; + } + + /** + * 清空当前登录用户 + */ + public static void clearCurrentUser() { + currentUser = null; + } + + public static String getToken() { + // 统一Header配置时用的token,没有的话要用空字符串,不能为null + String token = ""; + if (currentUser != null && currentUser.getSessionToken() != null) { + token = currentUser.getSessionToken(); + } + return token; + } + + /** + * 登出 + */ + public static void logout() { + clearCurrentUser(); + } + + /** + * 检测登录状态 + * + * @return true-已登录 false-未登录,会自动跳转至登录页 + */ + public static boolean checkLogin(Context context) { + if (currentUser == null) { + Intent intent = new Intent(context, LoginActivity.class); + intent.putExtra("checkLogin", true); + context.startActivity(intent); + return false; + } + return true; + } +} diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/anim/loading.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/anim/loading.xml new file mode 100644 index 0000000..cd9bcd7 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/anim/loading.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/color/txt_blue2gray_sel.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/color/txt_blue2gray_sel.xml new file mode 100644 index 0000000..41948c6 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/color/txt_blue2gray_sel.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_fav_grey2black_sel.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_fav_grey2black_sel.xml new file mode 100644 index 0000000..063616c --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_fav_grey2black_sel.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_home_grey2black_sel.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_home_grey2black_sel.xml new file mode 100644 index 0000000..c6240d5 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_home_grey2black_sel.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_more_grey2black_sel.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_more_grey2black_sel.xml new file mode 100644 index 0000000..1dde974 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_more_grey2black_sel.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_search_grey2black_sel.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_search_grey2black_sel.xml new file mode 100644 index 0000000..bedbb45 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_search_grey2black_sel.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_settings_grey2black_sel.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_settings_grey2black_sel.xml new file mode 100644 index 0000000..1a4c747 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/ic_settings_grey2black_sel.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/oval_progress.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/oval_progress.xml new file mode 100644 index 0000000..2d2115b --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/drawable/oval_progress.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_about.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_about.xml new file mode 100644 index 0000000..b3c88af --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_about.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_feed_back.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_feed_back.xml new file mode 100644 index 0000000..fc3a142 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_feed_back.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_input.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_input.xml new file mode 100644 index 0000000..a9b83d5 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_input.xml @@ -0,0 +1,23 @@ + + + + + + + + + + diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_login.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..8b7018f --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_main.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..5c5f747 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_regist.xml b/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_regist.xml new file mode 100644 index 0000000..aa35d08 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/app/src/main/res/layout/activity_regist.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + +