Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mvvmdemo
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
LouisWang
mvvmdemo
Commits
0c1fe3e6
Commit
0c1fe3e6
authored
Jun 24, 2020
by
TaylorZhang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(项目):完成mvvm-demo最小Demo
parent
ffc17dde
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
427 additions
and
18 deletions
+427
-18
mvvm-demo/src/main/AndroidManifest.xml
+1
-0
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/common/api/CommonApi.kt
+18
-0
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/common/http/ResponseConverter.kt
+33
-0
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/common/http/request.kt
+22
-0
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/common/tool/HttpTool.kt
+49
-0
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/common/view/BaseLifecycleActivity.kt
+26
-0
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/common/view/BaseViewModel.kt
+43
-0
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/demo/Application.kt
+26
-0
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/demo/api/DemoApi.kt
+34
-0
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/demo/enity/UserEntity.kt
+53
-0
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/demo/main/MainActivity.kt
+26
-6
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/demo/main/MainViewModel.kt
+61
-0
mvvm-demo/src/main/res/layout/activity_main.xml
+25
-12
mvvm-demo/src/main/res/values/strings.xml
+10
-0
No files found.
mvvm-demo/src/main/AndroidManifest.xml
View file @
0c1fe3e6
...
...
@@ -3,6 +3,7 @@
package=
"com.autocareai.mvvmdemo"
>
<application
android:name=
".demo.Application"
android:allowBackup=
"true"
android:icon=
"@mipmap/ic_launcher"
android:label=
"@string/app_name"
...
...
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/common/api/CommonApi.kt
0 → 100644
View file @
0c1fe3e6
package
com.autocareai.mvvmdemo.common.api
/**
* <pre>
* author : Taylor Zhang
* time : 2020/06/24
* desc : 通用网络请求接口
* version: 1.0.0
* </pre>
*/
object
CommonApi
{
/**
* api地址
*/
internal
val
API_URL
=
"https://wanandroid.com/"
}
\ No newline at end of file
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/common/http/ResponseConverter.kt
0 → 100644
View file @
0c1fe3e6
package
com.autocareai.mvvmdemo.common.http
import
androidx.lifecycle.LifecycleOwner
import
com.autocareai.lib.net.converter.IConverter
import
com.autocareai.lib.net.exception.BusinessErrorException
import
com.autocareai.lib.util.JsonUtil
import
okhttp3.ResponseBody
import
org.json.JSONObject
import
retrofit2.Response
/**
* <pre>
* author : Taylor Zhang
* time : 2020/06/24
* desc : 将Http响应数据转换成一个对象,去除最外层封装
* version: 1.0.0
* </pre>
*/
class
ResponseConverter
<
D
>(
private
val
clazz
:
Class
<
D
>)
:
IConverter
<
D
>
{
override
fun
convertResponse
(
owner
:
LifecycleOwner
?,
response
:
Response
<
ResponseBody
>):
D
?
{
val
json
=
response
.
body
()
?.
string
()
?:
return
null
val
jsonObj
=
JSONObject
(
json
)
val
code
=
jsonObj
.
getInt
(
"errorCode"
)
if
(
code
==
0
)
{
return
JsonUtil
.
parseObject
(
jsonObj
.
getJSONObject
(
"data"
).
toString
(),
clazz
)
}
else
{
throw
BusinessErrorException
(
code
,
jsonObj
.
getString
(
"errorMsg"
))
}
}
}
\ No newline at end of file
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/common/http/request.kt
0 → 100644
View file @
0c1fe3e6
package
com.autocareai.mvvmdemo.common.http
import
com.autocareai.lib.net.observable.HttpObservable
import
com.autocareai.lib.net.observable.HttpObservableImpl
import
com.autocareai.lib.net.request.BaseRequest
/**
* <pre>
* author : Taylor Zhang
* time : 2020/06/24
* desc : 网络请求基类扩展
* version: 1.0.0
* </pre>
*/
/**
* 将Http响应数据转换成一个对象,去除最外层封装
*/
inline
fun
<
reified
D
:
Any
>
BaseRequest
<*>.
asResponse
():
HttpObservable
<
D
>
{
return
HttpObservableImpl
(
this
,
ResponseConverter
(
D
::
class
.
java
))
}
\ No newline at end of file
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/common/tool/HttpTool.kt
0 → 100644
View file @
0c1fe3e6
package
com.autocareai.mvvmdemo.common.tool
import
com.autocareai.lib.net.HttpConfig
import
com.autocareai.lib.net.HttpUtil
import
com.autocareai.mvvmdemo.common.api.CommonApi
import
okhttp3.logging.HttpLoggingInterceptor
/**
* <pre>
* author : Taylor Zhang
* time : 2020/06/24
* desc : 网络请求工具类
* version: 1.0.0
* </pre>
*/
object
HttpTool
{
// 网络请求连接超时时间
private
const
val
DEFAULT_CONNECT_TIMEOUT
=
5000L
// 网络请求其他超时时间
private
const
val
OTHER_TIME_OUT
=
30000L
/**
* 初始化网络请求框架
*/
fun
init
()
{
val
httpConfig
=
HttpConfig
.
Builder
()
.
baseUrl
(
CommonApi
.
API_URL
)
// 设置全局超时时间
.
connectTimeoutMillis
(
DEFAULT_CONNECT_TIMEOUT
)
.
readTimeoutMillis
(
OTHER_TIME_OUT
)
.
writeTimeoutMillis
(
OTHER_TIME_OUT
)
.
setLogLevel
(
HttpLoggingInterceptor
.
Level
.
BODY
)
.
build
()
HttpUtil
.
initHttpConfig
(
httpConfig
)
// 初始化全局错误监听
initGlobalErrorListener
()
}
private
fun
initGlobalErrorListener
()
{
HttpUtil
.
setGlobalErrorListener
{
observable
,
code
,
message
->
// 处理全局错误
return
@setGlobalErrorListener
false
}
}
}
\ No newline at end of file
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/common/view/BaseLifecycleActivity.kt
0 → 100644
View file @
0c1fe3e6
package
com.autocareai.mvvmdemo.common.view
import
androidx.lifecycle.Observer
import
com.autocareai.lib.lifecycle.view.LibBaseLifecycleActivity
import
com.autocareai.lib.util.ToastUtil
/**
* <pre>
* author : Taylor Zhang
* time : 2020/06/24
* desc : 生命周期Activity基类
* version: 1.0.0
* </pre>
*/
abstract
class
BaseLifecycleActivity
<
VM
:
BaseViewModel
>
:
LibBaseLifecycleActivity
<
VM
>()
{
override
fun
initLifecycleObserver
()
{
super
.
initLifecycleObserver
()
mViewModel
.
shortToastEvent
.
observe
(
this
,
Observer
{
// 显示toast
ToastUtil
.
shortToast
(
it
)
})
}
}
\ No newline at end of file
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/common/view/BaseViewModel.kt
0 → 100644
View file @
0c1fe3e6
package
com.autocareai.mvvmdemo.common.view
import
android.widget.Toast
import
androidx.annotation.StringRes
import
com.autocareai.lib.lifecycle.extension.post
import
com.autocareai.lib.lifecycle.livedata.SingleLiveEvent
import
com.autocareai.lib.lifecycle.viewmodel.LibBaseViewModel
import
com.autocareai.lib.util.ResourcesUtil
/**
* <pre>
* author : Taylor Zhang
* time : 2020/06/24
* desc : 生命周期ViewModel基类
* version: 1.0.0
* </pre>
*/
open
class
BaseViewModel
:
LibBaseViewModel
()
{
/**
* 显示toast,时长为[Toast.LENGTH_SHORT]
*/
val
shortToastEvent
=
SingleLiveEvent
<
CharSequence
>()
/**
* 显示toast,时长为[Toast.LENGTH_SHORT]
*
* @param msg toast文本
*/
protected
fun
shortToast
(
msg
:
CharSequence
)
{
shortToastEvent
.
post
(
msg
)
}
/**
* 显示toast,时长为[Toast.LENGTH_SHORT]
*
* @param id toast文本资源id
*/
protected
fun
shortToast
(
@StringRes
id
:
Int
)
{
shortToastEvent
.
post
(
ResourcesUtil
.
getString
(
id
))
}
}
\ No newline at end of file
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/demo/Application.kt
0 → 100644
View file @
0c1fe3e6
package
com.autocareai.mvvmdemo.demo
import
com.autocareai.lib.application.LibApplication
import
com.autocareai.lib.util.LogUtil
import
com.autocareai.mvvmdemo.common.tool.HttpTool
/**
* <pre>
* author : Taylor Zhang
* time : 2020/06/24
* desc : Application
* version: 1.0.0
* </pre>
*/
class
Application
:
LibApplication
()
{
override
fun
isRelease
():
Boolean
{
// 初始化日志框架
LogUtil
.
init
()
HttpTool
.
init
()
return
false
}
}
\ No newline at end of file
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/demo/api/DemoApi.kt
0 → 100644
View file @
0c1fe3e6
package
com.autocareai.mvvmdemo.demo.api
import
com.autocareai.lib.net.HttpUtil
import
com.autocareai.lib.net.observable.HttpObservable
import
com.autocareai.mvvmdemo.common.http.asResponse
import
com.autocareai.mvvmdemo.demo.enity.UserEntity
/**
* <pre>
* author : Taylor Zhang
* time : 2020/06/24
* desc : Demo网络请求接口
* version: 1.0.0
* </pre>
*/
object
DemoApi
{
// 登录
private
const
val
LOGIN
=
"user/login"
/**
* 登录
*
* @param phone 手机号
* @param password 密码
*/
fun
login
(
phone
:
String
,
password
:
String
):
HttpObservable
<
UserEntity
>
{
return
HttpUtil
.
postForm
(
LOGIN
)
.
param
(
"username"
,
phone
)
.
param
(
"password"
,
password
)
.
asResponse
()
}
}
\ No newline at end of file
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/demo/enity/UserEntity.kt
0 → 100644
View file @
0c1fe3e6
package
com.autocareai.mvvmdemo.demo.enity
import
android.os.Parcelable
import
kotlinx.android.parcel.Parcelize
/**
* <pre>
* author : Taylor Zhang
* time : 2020/06/24
* desc : 用户数据
* version: 1.0.0
* </pre>
*/
@Parcelize
class
UserEntity
:
Parcelable
{
// TODO: 2020/6/24 这里不用使用 data class,普通的 class 即可
// TODO: 2020/6/24 每一个字段都需要写注释,对于多状态字段,或者布尔字段,要写明各种情况下的含义
// TODO: 2020/6/24 字段必须赋初值,使用简写即可,比如 var email = "",而不是 var email = ""
// xx
var
admin
=
false
// xx
var
chapterTops
=
ArrayList
<
String
>()
// xx
var
collectIds
=
ArrayList
<
String
>()
// xx
var
email
=
""
// xx
var
icon
=
""
// xx
var
id
=
""
// xx
var
nickname
=
""
// xx
var
password
=
""
// xx
var
token
=
""
// xx
var
type
=
0
// xx
var
username
=
""
}
\ No newline at end of file
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/demo/main/MainActivity.kt
View file @
0c1fe3e6
package
com.autocareai.mvvmdemo.demo.main
import
androidx.
appcompat.app.AppCompatActivity
import
android.os.Bundle
import
androidx.
lifecycle.Observer
import
com.autocareai.lib.extension.onClick
import
com.autocareai.mvvmdemo.R
import
com.autocareai.mvvmdemo.common.view.BaseLifecycleActivity
import
kotlinx.android.synthetic.main.activity_main.*
/**
* <pre>
...
...
@@ -12,10 +14,28 @@ import com.autocareai.mvvmdemo.R
* version: 1.0.0
* </pre>
*/
class
MainActivity
:
AppCompatActivity
()
{
class
MainActivity
:
BaseLifecycleActivity
<
MainViewModel
>
()
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
setContentView
(
R
.
layout
.
activity_main
)
override
fun
getLayoutId
():
Int
=
R
.
layout
.
activity_main
override
fun
getViewModelClass
():
Class
<
MainViewModel
>
=
MainViewModel
::
class
.
java
override
fun
initListener
()
{
super
.
initListener
()
// TODO: 2020/6/24 如果防止用户短时间多次点击,使用onClick,如果用户可以多次点击,还是使用原生的setOnClickListener
btnLogin
.
onClick
{
// 登录
mViewModel
.
login
(
this
,
etPhone
.
text
.
toString
(),
etPwd
.
text
.
toString
())
}
}
override
fun
initLifecycleObserver
()
{
super
.
initLifecycleObserver
()
mViewModel
.
toListEvent
.
observe
(
this
,
Observer
{
// 跳转至列表界面
// TODO: 2020/6/24 跳转至列表界面
})
}
}
mvvm-demo/src/main/java/com/autocareai/mvvmdemo/demo/main/MainViewModel.kt
0 → 100644
View file @
0c1fe3e6
package
com.autocareai.mvvmdemo.demo.main
import
androidx.lifecycle.LifecycleOwner
import
com.autocareai.lib.lifecycle.extension.post
import
com.autocareai.lib.lifecycle.livedata.SingleLiveEvent
import
com.autocareai.mvvmdemo.R
import
com.autocareai.mvvmdemo.common.view.BaseViewModel
import
com.autocareai.mvvmdemo.demo.api.DemoApi
import
com.autocareai.mvvmdemo.demo.enity.UserEntity
/**
* <pre>
* author : Taylor Zhang
* time : 2020/06/24
* desc : 主界面ViewModel
* version: 1.0.0
* </pre>
*/
class
MainViewModel
:
BaseViewModel
()
{
/**
* 跳转至列表界面事件
*/
val
toListEvent
=
SingleLiveEvent
<
UserEntity
>()
/**
* 登录
*/
fun
login
(
owner
:
LifecycleOwner
,
phone
:
String
,
password
:
String
)
{
checkInput
(
owner
,
phone
,
password
)
}
private
fun
checkInput
(
owner
:
LifecycleOwner
,
phone
:
String
,
password
:
String
)
{
// TODO: 2020/6/24 检查用户输入是否合规的逻辑也应该放在ViewModel中
if
(
phone
.
isEmpty
())
{
shortToast
(
R
.
string
.
main_please_input_phone
)
return
}
if
(
password
.
isEmpty
())
{
shortToast
(
R
.
string
.
main_please_input_password
)
return
}
realLogin
(
owner
,
phone
,
password
)
}
private
fun
realLogin
(
owner
:
LifecycleOwner
,
phone
:
String
,
password
:
String
)
{
DemoApi
.
login
(
phone
,
password
)
.
attachLifecycle
(
owner
)
.
onSuccess
{
shortToast
(
R
.
string
.
main_login_success
)
toListEvent
.
post
(
it
)
}
.
onError
{
_
,
message
->
shortToast
(
message
)
}
.
async
()
}
}
\ No newline at end of file
mvvm-demo/src/main/res/layout/activity_main.xml
View file @
0c1fe3e6
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
tools:context=
".demo.main.MainActivity"
>
android:gravity=
"center"
android:orientation=
"vertical"
android:paddingStart=
"25dp"
android:paddingEnd=
"25dp"
>
<TextView
<!--todo: EditText的简写应该是et,不是ed-->
<EditText
android:id=
"@+id/etPhone"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:hint=
"@string/main_input_phone_hint"
android:textSize=
"16sp"
/>
<EditText
android:id=
"@+id/etPwd"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:hint=
"@string/main_input_password_hint"
android:textSize=
"16sp"
/>
<Button
android:id=
"@+id/btnLogin"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"Hello World!"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
android:text=
"@string/main_login"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
</LinearLayout>
\ No newline at end of file
mvvm-demo/src/main/res/values/strings.xml
View file @
0c1fe3e6
<resources>
<string
name=
"app_name"
>
mvvm-demo
</string>
<!--todo: 项目中显示和toast提示的文案,只要是放在客户端的,都要定义在资源文件中-->
<!--todo: 对于需要拼接显示的文案,使用格式化的方式处理文本-->
<string
name=
"main_input_phone_hint"
>
请输入手机号
</string>
<string
name=
"main_input_password_hint"
>
请输入密码
</string>
<string
name=
"main_login"
>
登录
</string>
<string
name=
"main_please_input_phone"
>
请填写手机号
</string>
<string
name=
"main_please_input_password"
>
请填写密码
</string>
<string
name=
"main_login_success"
>
登录成功
</string>
</resources>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment