Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
beyond-clouds-android
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
云深项目组
beyond-clouds-android
Commits
c9fbcaf0
Commit
c9fbcaf0
authored
Mar 20, 2020
by
段启岩
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
用户token刷新完成
parent
c5e2294c
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
214 additions
and
9 deletions
+214
-9
app/src/main/java/cn/yunliyunwai/beyondclouds/adapter/common/LiveDataCallAdapter.java
+112
-5
app/src/main/java/cn/yunliyunwai/beyondclouds/adapter/common/LiveDataCallAdapterFactory.java
+14
-1
app/src/main/java/cn/yunliyunwai/beyondclouds/data/source/IPostRepository.java
+4
-0
app/src/main/java/cn/yunliyunwai/beyondclouds/data/source/impl/PostRepositoryImpl.java
+10
-0
app/src/main/java/cn/yunliyunwai/beyondclouds/data/source/remote/PostApiStore.java
+20
-0
app/src/main/java/cn/yunliyunwai/beyondclouds/di/module/AppModule.java
+2
-2
app/src/main/java/cn/yunliyunwai/beyondclouds/viewmodel/AuthenticationViewModel.java
+47
-0
app/src/main/java/cn/yunliyunwai/beyondclouds/viewmodel/DynamicListFragmentViewModel.java
+5
-1
No files found.
app/src/main/java/cn/yunliyunwai/beyondclouds/adapter/common/LiveDataCallAdapter.java
View file @
c9fbcaf0
package
cn
.
yunliyunwai
.
beyondclouds
.
adapter
.
common
;
package
cn
.
yunliyunwai
.
beyondclouds
.
adapter
.
common
;
import
android.util.Log
;
import
androidx.lifecycle.LiveData
;
import
androidx.lifecycle.LiveData
;
import
java.lang.reflect.Type
;
import
java.lang.reflect.Type
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
cn.yunliyunwai.beyondclouds.data.model.AuthenticationResult
;
import
cn.yunliyunwai.beyondclouds.data.model.Result
;
import
cn.yunliyunwai.beyondclouds.data.model.Result
;
import
cn.yunliyunwai.beyondclouds.viewmodel.AuthenticationViewModel
;
import
okhttp3.OkHttpClient
;
import
retrofit2.Call
;
import
retrofit2.Call
;
import
retrofit2.CallAdapter
;
import
retrofit2.CallAdapter
;
import
retrofit2.Callback
;
import
retrofit2.Callback
;
import
retrofit2.Response
;
import
retrofit2.Response
;
import
retrofit2.Retrofit
;
import
retrofit2.converter.gson.GsonConverterFactory
;
import
retrofit2.http.Body
;
import
retrofit2.http.POST
;
public
class
LiveDataCallAdapter
<
T
>
implements
CallAdapter
<
T
,
LiveData
<
T
>>
{
public
class
LiveDataCallAdapter
<
T
>
implements
CallAdapter
<
T
,
LiveData
<
T
>>
{
private
Type
responseType
;
private
Type
responseType
;
private
AuthenticationViewModel
authenticationViewModel
;
public
LiveDataCallAdapter
(
Type
responseType
)
{
public
LiveDataCallAdapter
(
Type
responseType
,
AuthenticationViewModel
authenticationViewModel
)
{
this
.
responseType
=
responseType
;
this
.
responseType
=
responseType
;
this
.
authenticationViewModel
=
authenticationViewModel
;
}
}
public
Type
responseType
()
{
public
Type
responseType
()
{
...
@@ -26,15 +38,63 @@ public class LiveDataCallAdapter<T> implements CallAdapter<T, LiveData<T>> {
...
@@ -26,15 +38,63 @@ public class LiveDataCallAdapter<T> implements CallAdapter<T, LiveData<T>> {
public
LiveData
<
T
>
adapt
(
Call
<
T
>
call
)
{
public
LiveData
<
T
>
adapt
(
Call
<
T
>
call
)
{
return
new
LiveData
<
T
>()
{
return
new
LiveData
<
T
>()
{
private
AtomicBoolean
started
=
new
AtomicBoolean
(
false
);
private
AtomicBoolean
started
=
new
AtomicBoolean
(
false
);
@Override
protected
void
onActive
()
{
private
void
doRequest
(
boolean
reRequest
)
{
super
.
onActive
();
Call
<
T
>
realCall
=
call
;
if
(
reRequest
)
{
started
.
set
(
false
);
realCall
=
call
.
clone
();
}
if
(
started
.
compareAndSet
(
false
,
true
))
{
if
(
started
.
compareAndSet
(
false
,
true
))
{
c
all
.
enqueue
(
new
Callback
<
T
>()
{
realC
all
.
enqueue
(
new
Callback
<
T
>()
{
@Override
@Override
public
void
onResponse
(
Call
<
T
>
call
,
Response
<
T
>
response
)
{
public
void
onResponse
(
Call
<
T
>
call
,
Response
<
T
>
response
)
{
if
(
response
.
code
()
==
200
)
{
if
(
response
.
code
()
==
200
)
{
// 请求成功
postValue
(
response
.
body
());
postValue
(
response
.
body
());
}
else
if
(
response
.
code
()
==
401
&&
!
reRequest
)
{
// 认证失败,可能是token失效,尝试用refreshToken刷新
AuthenticationViewModel
.
AuthenticationState
authenticationState
=
authenticationViewModel
.
getAuthenticationState
().
getValue
();
Log
.
d
(
getClass
().
getName
(),
"token过期,"
+
authenticationState
.
name
());
// 用户之前没有认证,直接返回未认证
if
(
authenticationState
!=
AuthenticationViewModel
.
AuthenticationState
.
AUTHENTICATED
)
{
postValue
((
T
)
new
Result
(-
2
,
"未认证"
,
response
.
errorBody
()));
return
;
}
// 开始刷新token
Log
.
d
(
getClass
().
getName
(),
"开始刷新token,refreshToken:,"
+
authenticationViewModel
.
getRefreshToken
());
Call
<
Result
<
AuthenticationResult
>>
refreshTokenCall
=
createRefreshTokenApiStore
().
refreshToken
(
IRefreshTokenApiStore
.
RefreshTokenForm
.
create
(
authenticationViewModel
.
getRefreshToken
()));
refreshTokenCall
.
enqueue
(
new
Callback
<
Result
<
AuthenticationResult
>>()
{
@Override
public
void
onResponse
(
Call
<
Result
<
AuthenticationResult
>>
call
,
Response
<
Result
<
AuthenticationResult
>>
response
)
{
Result
<
AuthenticationResult
>
result
=
response
.
body
();
if
(
result
.
getCode
()
!=
0
)
{
// token刷新失败,将当前认证状态改为认证已过期
authenticationViewModel
.
makeAuthenticationExpire
();
postValue
((
T
)
new
Result
(-
2
,
"认证过期"
,
response
.
errorBody
()));
Log
.
d
(
getClass
().
getName
(),
"token刷新失败."
);
}
else
{
// token刷新成功,重新请求
authenticationViewModel
.
refreshToken
(
result
.
getData
());
Log
.
d
(
getClass
().
getName
(),
"刷新token成功,正在重新发起请求."
);
doRequest
(
true
);
}
}
@Override
public
void
onFailure
(
Call
<
Result
<
AuthenticationResult
>>
call
,
Throwable
t
)
{
// token刷新失败,将当前认证状态改为认证已过期
authenticationViewModel
.
makeAuthenticationExpire
();
postValue
((
T
)
new
Result
(-
2
,
"认证过期"
,
response
.
errorBody
()));
Log
.
d
(
getClass
().
getName
(),
"token刷新失败."
);
}
});
}
else
{
}
else
{
postValue
((
T
)
new
Result
(-
10
,
"请求出错"
,
response
.
errorBody
()));
postValue
((
T
)
new
Result
(-
10
,
"请求出错"
,
response
.
errorBody
()));
}
}
...
@@ -49,6 +109,53 @@ public class LiveDataCallAdapter<T> implements CallAdapter<T, LiveData<T>> {
...
@@ -49,6 +109,53 @@ public class LiveDataCallAdapter<T> implements CallAdapter<T, LiveData<T>> {
});
});
}
}
}
}
@Override
protected
void
onActive
()
{
super
.
onActive
();
doRequest
(
false
);
}
};
};
}
}
private
Retrofit
createCommonRetrofit
()
{
OkHttpClient
okHttpClient
=
new
OkHttpClient
.
Builder
()
.
connectTimeout
(
10
,
TimeUnit
.
SECONDS
)
.
readTimeout
(
20
,
TimeUnit
.
SECONDS
)
.
writeTimeout
(
20
,
TimeUnit
.
SECONDS
).
build
();
return
new
Retrofit
.
Builder
()
.
baseUrl
(
"https://api.yunliyunwai.cn/api/"
)
.
client
(
okHttpClient
)
.
addConverterFactory
(
GsonConverterFactory
.
create
())
.
build
();
}
private
IRefreshTokenApiStore
createRefreshTokenApiStore
()
{
return
createCommonRetrofit
().
create
(
IRefreshTokenApiStore
.
class
);
}
private
interface
IRefreshTokenApiStore
{
class
RefreshTokenForm
{
private
String
refreshToken
;
private
RefreshTokenForm
(
String
refreshToken
)
{
this
.
refreshToken
=
refreshToken
;
}
public
static
RefreshTokenForm
create
(
String
refreshToken
)
{
return
new
RefreshTokenForm
(
refreshToken
);
}
public
String
getRefreshToken
()
{
return
refreshToken
;
}
public
void
setRefreshToken
(
String
refreshToken
)
{
this
.
refreshToken
=
refreshToken
;
}
}
@POST
(
"auth/refresh"
)
Call
<
Result
<
AuthenticationResult
>>
refreshToken
(
@Body
RefreshTokenForm
refreshTokenForm
);
}
}
}
app/src/main/java/cn/yunliyunwai/beyondclouds/adapter/common/LiveDataCallAdapterFactory.java
View file @
c9fbcaf0
...
@@ -8,11 +8,24 @@ import java.lang.annotation.Annotation;
...
@@ -8,11 +8,24 @@ import java.lang.annotation.Annotation;
import
java.lang.reflect.ParameterizedType
;
import
java.lang.reflect.ParameterizedType
;
import
java.lang.reflect.Type
;
import
java.lang.reflect.Type
;
import
javax.inject.Inject
;
import
javax.inject.Singleton
;
import
cn.yunliyunwai.beyondclouds.data.model.Result
;
import
cn.yunliyunwai.beyondclouds.data.model.Result
;
import
cn.yunliyunwai.beyondclouds.viewmodel.AuthenticationViewModel
;
import
retrofit2.CallAdapter
;
import
retrofit2.CallAdapter
;
import
retrofit2.Retrofit
;
import
retrofit2.Retrofit
;
@Singleton
public
class
LiveDataCallAdapterFactory
extends
CallAdapter
.
Factory
{
public
class
LiveDataCallAdapterFactory
extends
CallAdapter
.
Factory
{
private
AuthenticationViewModel
authenticationViewModel
;
@Inject
public
LiveDataCallAdapterFactory
(
AuthenticationViewModel
authenticationViewModel
)
{
this
.
authenticationViewModel
=
authenticationViewModel
;
}
@Nullable
@Nullable
@Override
@Override
public
CallAdapter
<?,
?>
get
(
Type
returnType
,
Annotation
[]
annotations
,
Retrofit
retrofit
)
{
public
CallAdapter
<?,
?>
get
(
Type
returnType
,
Annotation
[]
annotations
,
Retrofit
retrofit
)
{
...
@@ -28,6 +41,6 @@ public class LiveDataCallAdapterFactory extends CallAdapter.Factory {
...
@@ -28,6 +41,6 @@ public class LiveDataCallAdapterFactory extends CallAdapter.Factory {
if
(!(
observableType
instanceof
ParameterizedType
))
{
if
(!(
observableType
instanceof
ParameterizedType
))
{
throw
new
IllegalArgumentException
(
"resource must be parameterized"
);
throw
new
IllegalArgumentException
(
"resource must be parameterized"
);
}
}
return
new
LiveDataCallAdapter
<>(
observableType
);
return
new
LiveDataCallAdapter
<>(
observableType
,
authenticationViewModel
);
}
}
}
}
app/src/main/java/cn/yunliyunwai/beyondclouds/data/source/IPostRepository.java
View file @
c9fbcaf0
...
@@ -11,4 +11,8 @@ public interface IPostRepository {
...
@@ -11,4 +11,8 @@ public interface IPostRepository {
LiveData
<
Result
<
Page
<
Post
>>>
getLatestPostList
(
Integer
type
,
Integer
page
,
int
pageSize
);
LiveData
<
Result
<
Page
<
Post
>>>
getLatestPostList
(
Integer
type
,
Integer
page
,
int
pageSize
);
LiveData
<
Result
<
Page
<
Post
>>>
getRecommendPostList
(
Integer
page
,
int
pageSize
);
LiveData
<
Result
<
Page
<
Post
>>>
getRecommendPostList
(
Integer
page
,
int
pageSize
);
LiveData
<
Result
<
Page
<
Post
>>>
getMyPostList
(
Integer
page
,
int
pageSize
);
LiveData
<
Result
<
Page
<
Post
>>>
getFollowedPostList
(
Integer
page
,
int
pageSize
);
}
}
app/src/main/java/cn/yunliyunwai/beyondclouds/data/source/impl/PostRepositoryImpl.java
View file @
c9fbcaf0
...
@@ -30,4 +30,14 @@ public class PostRepositoryImpl implements IPostRepository {
...
@@ -30,4 +30,14 @@ public class PostRepositoryImpl implements IPostRepository {
public
LiveData
<
Result
<
Page
<
Post
>>>
getRecommendPostList
(
Integer
page
,
int
pageSize
)
{
public
LiveData
<
Result
<
Page
<
Post
>>>
getRecommendPostList
(
Integer
page
,
int
pageSize
)
{
return
postApiStore
.
getRecommendBlogList
(
page
,
pageSize
);
return
postApiStore
.
getRecommendBlogList
(
page
,
pageSize
);
}
}
@Override
public
LiveData
<
Result
<
Page
<
Post
>>>
getMyPostList
(
Integer
page
,
int
pageSize
)
{
return
postApiStore
.
getMyPostList
(
page
,
pageSize
);
}
@Override
public
LiveData
<
Result
<
Page
<
Post
>>>
getFollowedPostList
(
Integer
page
,
int
pageSize
)
{
return
postApiStore
.
getFollowedPostList
(
page
,
pageSize
);
}
}
}
app/src/main/java/cn/yunliyunwai/beyondclouds/data/source/remote/PostApiStore.java
View file @
c9fbcaf0
...
@@ -29,4 +29,24 @@ public interface PostApiStore {
...
@@ -29,4 +29,24 @@ public interface PostApiStore {
@GET
(
"posts"
)
@GET
(
"posts"
)
LiveData
<
Result
<
Page
<
Post
>>>
getLatestPostList
(
@Query
(
"type"
)
Integer
type
,
@Query
(
"page"
)
Integer
page
,
LiveData
<
Result
<
Page
<
Post
>>>
getLatestPostList
(
@Query
(
"type"
)
Integer
type
,
@Query
(
"page"
)
Integer
page
,
@Query
(
"size"
)
int
pageSize
);
@Query
(
"size"
)
int
pageSize
);
/**
* 我的动态
* @param page
* @param pageSize
* @return
*/
@GET
(
"my/posts"
)
LiveData
<
Result
<
Page
<
Post
>>>
getMyPostList
(
@Query
(
"page"
)
Integer
page
,
@Query
(
"size"
)
int
pageSize
);
/**
* 我关注的人的的动态
* @param page
* @param pageSize
* @return
*/
@GET
(
"posts/followed"
)
LiveData
<
Result
<
Page
<
Post
>>>
getFollowedPostList
(
@Query
(
"page"
)
Integer
page
,
@Query
(
"size"
)
int
pageSize
);
}
}
app/src/main/java/cn/yunliyunwai/beyondclouds/di/module/AppModule.java
View file @
c9fbcaf0
...
@@ -109,7 +109,7 @@ public class AppModule {
...
@@ -109,7 +109,7 @@ public class AppModule {
@Singleton
@Singleton
@Provides
@Provides
public
Retrofit
provideRetrofit
(
OkHttpClient
okHttpClient
)
{
public
Retrofit
provideRetrofit
(
OkHttpClient
okHttpClient
,
LiveDataCallAdapterFactory
liveDataCallAdapterFactory
)
{
Gson
gson
=
new
GsonBuilder
().
registerTypeAdapter
(
Date
.
class
,
new
JsonDeserializer
<
Date
>()
{
Gson
gson
=
new
GsonBuilder
().
registerTypeAdapter
(
Date
.
class
,
new
JsonDeserializer
<
Date
>()
{
public
Date
deserialize
(
JsonElement
json
,
Type
typeOfT
,
JsonDeserializationContext
context
)
throws
JsonParseException
{
public
Date
deserialize
(
JsonElement
json
,
Type
typeOfT
,
JsonDeserializationContext
context
)
throws
JsonParseException
{
String
dateStr
=
json
.
getAsJsonPrimitive
().
getAsString
();
String
dateStr
=
json
.
getAsJsonPrimitive
().
getAsString
();
...
@@ -125,7 +125,7 @@ public class AppModule {
...
@@ -125,7 +125,7 @@ public class AppModule {
return
new
Retrofit
.
Builder
()
return
new
Retrofit
.
Builder
()
.
baseUrl
(
"https://api.yunliyunwai.cn/api/"
)
.
baseUrl
(
"https://api.yunliyunwai.cn/api/"
)
.
client
(
okHttpClient
)
.
client
(
okHttpClient
)
.
addCallAdapterFactory
(
new
LiveDataCallAdapterFactory
()
)
.
addCallAdapterFactory
(
liveDataCallAdapterFactory
)
.
addConverterFactory
(
GsonConverterFactory
.
create
(
gson
))
.
addConverterFactory
(
GsonConverterFactory
.
create
(
gson
))
.
build
();
.
build
();
}
}
...
...
app/src/main/java/cn/yunliyunwai/beyondclouds/viewmodel/AuthenticationViewModel.java
View file @
c9fbcaf0
...
@@ -47,6 +47,11 @@ public class AuthenticationViewModel extends ViewModel {
...
@@ -47,6 +47,11 @@ public class AuthenticationViewModel extends ViewModel {
AUTHENTICATE_FAILURE
,
AUTHENTICATE_FAILURE
,
/**
/**
* 认证过期
*/
AUTHENTICATE_EXPIRED
,
/**
* 已认证
* 已认证
*/
*/
AUTHENTICATED
AUTHENTICATED
...
@@ -163,6 +168,10 @@ public class AuthenticationViewModel extends ViewModel {
...
@@ -163,6 +168,10 @@ public class AuthenticationViewModel extends ViewModel {
return
mToken
;
return
mToken
;
}
}
public
String
getRefreshToken
()
{
return
mRefreshToken
;
}
public
String
getAuthErrorMsg
()
{
public
String
getAuthErrorMsg
()
{
return
mAuthErrorMsg
;
return
mAuthErrorMsg
;
}
}
...
@@ -258,6 +267,17 @@ public class AuthenticationViewModel extends ViewModel {
...
@@ -258,6 +267,17 @@ public class AuthenticationViewModel extends ViewModel {
}
}
/**
/**
* 将当前认证状态置为认证已过期
*/
public
void
makeAuthenticationExpire
()
{
mToken
=
null
;
mRefreshToken
=
null
;
mUserInfo
=
null
;
authenticationState
.
postValue
(
AuthenticationState
.
AUTHENTICATE_EXPIRED
);
removeUserInfoAndTokenToLocal
();
}
/**
* 将用户信息和token保存到本地
* 将用户信息和token保存到本地
*/
*/
private
void
saveUserInfoAndTokenToLocal
()
{
private
void
saveUserInfoAndTokenToLocal
()
{
...
@@ -270,6 +290,18 @@ public class AuthenticationViewModel extends ViewModel {
...
@@ -270,6 +290,18 @@ public class AuthenticationViewModel extends ViewModel {
}
}
/**
/**
* 将用户信息和token从本地移除
*/
private
void
removeUserInfoAndTokenToLocal
()
{
SharedPreferences
sharedPreferences
=
mContext
.
getSharedPreferences
(
SHARED_PREFERENCES_NAME_AUTHENTICATION
,
Context
.
MODE_PRIVATE
);
sharedPreferences
.
edit
()
.
remove
(
SHARED_PREFERENCES_AUTHENTICATION_KEY_TOKEN
)
.
remove
(
SHARED_PREFERENCES_AUTHENTICATION_KEY_REFRESH_TOKEN
)
.
remove
(
SHARED_PREFERENCES_AUTHENTICATION_KEY_USER_INFO
)
.
commit
();
}
/**
* 从本地加载token和用户信息
* 从本地加载token和用户信息
*/
*/
private
void
loadTokenAndUserInfoFromLocal
()
{
private
void
loadTokenAndUserInfoFromLocal
()
{
...
@@ -286,4 +318,19 @@ public class AuthenticationViewModel extends ViewModel {
...
@@ -286,4 +318,19 @@ public class AuthenticationViewModel extends ViewModel {
this
.
authenticationState
.
setValue
(
AuthenticationState
.
UN_AUTHENTICATE
);
this
.
authenticationState
.
setValue
(
AuthenticationState
.
UN_AUTHENTICATE
);
}
}
}
}
/**
* 刷新token
* @param authenticationResult
*/
public
void
refreshToken
(
AuthenticationResult
authenticationResult
)
{
mToken
=
authenticationResult
.
getAccessToken
();
mRefreshToken
=
authenticationResult
.
getRefreshToken
();
SharedPreferences
sharedPreferences
=
mContext
.
getSharedPreferences
(
SHARED_PREFERENCES_NAME_AUTHENTICATION
,
Context
.
MODE_PRIVATE
);
sharedPreferences
.
edit
()
.
putString
(
SHARED_PREFERENCES_AUTHENTICATION_KEY_TOKEN
,
mToken
)
.
putString
(
SHARED_PREFERENCES_AUTHENTICATION_KEY_REFRESH_TOKEN
,
mRefreshToken
)
.
commit
();
}
}
}
app/src/main/java/cn/yunliyunwai/beyondclouds/viewmodel/DynamicListFragmentViewModel.java
View file @
c9fbcaf0
...
@@ -27,9 +27,13 @@ public class DynamicListFragmentViewModel extends PageableViewModel<Post> {
...
@@ -27,9 +27,13 @@ public class DynamicListFragmentViewModel extends PageableViewModel<Post> {
postRepository
.
getRecommendPostList
(
page
,
defaultPageSize
).
observeForever
(
observer
);
postRepository
.
getRecommendPostList
(
page
,
defaultPageSize
).
observeForever
(
observer
);
break
;
break
;
case
LATEST:
case
LATEST:
postRepository
.
getLatestPostList
(
null
,
page
,
defaultPageSize
).
observeForever
(
observer
);
break
;
case
FOLLOW:
case
FOLLOW:
postRepository
.
getFollowedPostList
(
page
,
defaultPageSize
).
observeForever
(
observer
);
break
;
case
MY:
case
MY:
postRepository
.
get
LatestPostList
(
null
,
page
,
defaultPageSize
).
observeForever
(
observer
);
postRepository
.
get
MyPostList
(
page
,
defaultPageSize
).
observeForever
(
observer
);
break
;
break
;
case
WORDS:
case
WORDS:
postRepository
.
getLatestPostList
(
0
,
page
,
defaultPageSize
).
observeForever
(
observer
);
postRepository
.
getLatestPostList
(
0
,
page
,
defaultPageSize
).
observeForever
(
observer
);
...
...
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