├── .gitignore
├── LICENSE
├── README.md
├── XML.patch
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ └── litepal.xml
│ ├── java
│ └── com
│ │ └── lfork
│ │ └── a98620
│ │ └── lfree
│ │ ├── articlecontent
│ │ ├── ArticleContentActivity.java
│ │ ├── ArticleContentActivityViewModel.java
│ │ ├── CommunityComment.java
│ │ ├── CommunityCommentAdapter.java
│ │ └── LightTextView.java
│ │ ├── base
│ │ ├── BaseActivity.java
│ │ ├── BaseViewModel.java
│ │ ├── Config.java
│ │ ├── FreeApplication.java
│ │ ├── MyApplication.java
│ │ ├── adapter
│ │ │ ├── ListViewAdapter.java
│ │ │ └── RecyclerViewItemAdapter.java
│ │ ├── bindingadapter
│ │ │ ├── ImageBinding.java
│ │ │ └── ListBinding.java
│ │ ├── customview
│ │ │ ├── MySwipeRefreshLayout.java
│ │ │ ├── PopupDialog.java
│ │ │ ├── PopupDialogOnclickListener.java
│ │ │ └── RefreshFooterView.java
│ │ ├── image
│ │ │ ├── GlideEngine.java
│ │ │ ├── GlideImageLoader.java
│ │ │ └── ImageTool.java
│ │ ├── network
│ │ │ ├── HttpService.java
│ │ │ ├── MyRetrofitCallBack.kt
│ │ │ └── Result.kt
│ │ ├── thread
│ │ │ └── MyThreadFactory.java
│ │ └── viewmodel
│ │ │ ├── GoodsViewModel.java
│ │ │ ├── UserViewModel.java
│ │ │ └── ViewModelNavigator.java
│ │ ├── chatwindow
│ │ ├── ChatWindowActivity.java
│ │ ├── ChatWindowNavigator.java
│ │ ├── ChatWindowViewModel.java
│ │ └── MessageListAdapter.java
│ │ ├── data
│ │ ├── DataSource.kt
│ │ ├── base
│ │ │ ├── api
│ │ │ │ ├── CommunityApi.kt
│ │ │ │ ├── GoodsApi.kt
│ │ │ │ └── UserApi.kt
│ │ │ └── entity
│ │ │ │ ├── Category.kt
│ │ │ │ ├── Goods.kt
│ │ │ │ ├── GoodsDetailInfo.kt
│ │ │ │ ├── IMUser.kt
│ │ │ │ ├── Review.kt
│ │ │ │ ├── School.kt
│ │ │ │ └── User.kt
│ │ ├── community
│ │ │ ├── CommunityDataSource.java
│ │ │ ├── local
│ │ │ │ └── CommunityLocalDataSource.java
│ │ │ └── remote
│ │ │ │ └── CommunityRemoteDataSource.java
│ │ ├── goods
│ │ │ ├── GoodsDataRepository.kt
│ │ │ ├── GoodsDataSource.kt
│ │ │ ├── local
│ │ │ │ └── GoodsLocalDataSource.kt
│ │ │ └── remote
│ │ │ │ └── GoodsRemoteDataSource.kt
│ │ ├── imdata
│ │ │ ├── IMDataRepository.kt
│ │ │ ├── IMDataSource.kt
│ │ │ ├── MessageDataRepository.kt
│ │ │ ├── MessageDataSource.kt
│ │ │ ├── local
│ │ │ │ ├── IMLocalDataSource.kt
│ │ │ │ └── MessageLocalDataSource.kt
│ │ │ └── remote
│ │ │ │ ├── IMRemoteDataSource.kt
│ │ │ │ └── MessageRemoteDataSource.kt
│ │ └── user
│ │ │ ├── UserDataRepository.kt
│ │ │ ├── UserDataSource.kt
│ │ │ ├── local
│ │ │ └── UserLocalDataSource.kt
│ │ │ └── remote
│ │ │ └── UserRemoteDataSource.kt
│ │ ├── goodsdetail
│ │ ├── GoodsDetailActivity.java
│ │ ├── GoodsDetailNavigator.java
│ │ ├── GoodsDetailViewModel.java
│ │ └── ReviewItemViewModel.java
│ │ ├── goodsuploadupdate
│ │ ├── GoodsCategoriesBinding.java
│ │ ├── GoodsUploadUpdateActivity.java
│ │ ├── GoodsUploadUpdateNavigator.java
│ │ └── GoodsUploadUpdateViewModel.java
│ │ ├── imagebrowser
│ │ └── ImageBrowserActivity.java
│ │ ├── imservice
│ │ ├── Config.java
│ │ ├── MessageListener.java
│ │ ├── MessageService.java
│ │ ├── MessageTask.java
│ │ ├── TCPConnection.java
│ │ ├── UDPConnection.java
│ │ ├── UDPMessageMaid.java
│ │ ├── message
│ │ │ ├── Message.java
│ │ │ ├── MessageContentType.java
│ │ │ ├── MessageHelper.java
│ │ │ ├── MessageStatus.java
│ │ │ └── MessageType.java
│ │ └── request
│ │ │ ├── LoginListener.java
│ │ │ ├── RegisterListener.java
│ │ │ ├── Request.java
│ │ │ ├── Result.java
│ │ │ └── UserRequestType.java
│ │ ├── login
│ │ ├── LoginActivity.java
│ │ ├── LoginNavigator.java
│ │ └── LoginViewModel.java
│ │ ├── main
│ │ ├── MainActivity.java
│ │ ├── chatlist
│ │ │ ├── ChatListFragment.java
│ │ │ ├── ChatListFragmentViewModel.java
│ │ │ ├── ChatListItemNavigator.java
│ │ │ └── ChatListItemViewModel.java
│ │ ├── community
│ │ │ ├── CommunityArticle.java
│ │ │ ├── CommunityArticleAdapter.java
│ │ │ ├── CommunityBindingAdapter.java
│ │ │ ├── CommunityCallback.java
│ │ │ ├── CommunityFragment.java
│ │ │ └── CommunityFragmentViewModel.java
│ │ ├── index
│ │ │ ├── GoodsItemNavigator.java
│ │ │ ├── GoodsItemViewModel.java
│ │ │ ├── GoodsRecyclerViewItemAdapter.java
│ │ │ ├── IndexFragment.java
│ │ │ ├── IndexFragmentNavigator.java
│ │ │ ├── IndexFragmentViewModel.java
│ │ │ ├── PagerDataRefreshListener.java
│ │ │ ├── PagerItemAdapter.java
│ │ │ ├── PagerItemView.java
│ │ │ ├── PagerItemViewModel.java
│ │ │ ├── PagerItemViewNavigator.java
│ │ │ └── PagersDataBinding.java
│ │ ├── myinfo
│ │ │ ├── MyInfoFragment.java
│ │ │ ├── MyInfoFragmentNavigator.java
│ │ │ └── MyInfoFragmentViewModel.java
│ │ └── publishinfo
│ │ │ └── PublishInfoFragment.java
│ │ ├── mygoods
│ │ ├── MyGoodsActivity.java
│ │ ├── MyGoodsActivityNavigator.java
│ │ ├── MyGoodsItemNavigator.java
│ │ ├── MyGoodsItemViewModel.java
│ │ └── MyGoodsViewModel.java
│ │ ├── publisharticle
│ │ └── PublishArticleActivity.java
│ │ ├── register
│ │ ├── RegisterActivity.java
│ │ ├── RegisterInfoViewModel.java
│ │ └── RegisterNavigator.java
│ │ ├── searchresult
│ │ ├── GoodsSearchActivity.java
│ │ ├── GoodsSearchItemViewModel.java
│ │ ├── GoodsSearchNavigator.java
│ │ └── GoodsSearchViewModel.java
│ │ ├── settings
│ │ └── SettingsActivity.kt
│ │ ├── userinfo
│ │ ├── UserInfoActivity.java
│ │ └── UserInfoViewModel.java
│ │ ├── userinfoedit
│ │ ├── UserInfoEditActivity.java
│ │ ├── UserInfoEditNavigator.java
│ │ └── UserInfoEditViewModel.java
│ │ ├── userinfothis
│ │ ├── UserInfoThisActivity.java
│ │ └── UserInfoThisViewModel.java
│ │ ├── util
│ │ ├── JSONUtil.java
│ │ ├── LFreeGlideModel.java
│ │ ├── Print.java
│ │ ├── QMUI
│ │ │ ├── QMUIDeviceHelper.java
│ │ │ ├── QMUIDisplayHelper.java
│ │ │ ├── QMUILangHelper.java
│ │ │ ├── QMUILog.java
│ │ │ └── QMUIStatusBarHelper.java
│ │ ├── ShareUtil.java
│ │ ├── SharedPrefUtil.java
│ │ ├── ThreadUtil.java
│ │ ├── TimeUtil.java
│ │ ├── ToastUtil.java
│ │ ├── UserValidation.java
│ │ ├── Utils.java
│ │ ├── file
│ │ │ ├── FileHelper.java
│ │ │ └── UriHelper.java
│ │ └── ui
│ │ │ └── MyItemDecoration.java
│ │ ├── webclient
│ │ └── WebClient.java
│ │ └── welcome
│ │ └── WelcomeActivity.java
│ └── res
│ ├── drawable-hdpi
│ ├── chatwindow_mesage_left.9.png
│ ├── chatwindow_message_right.9.png
│ └── goods_upload_icon.png
│ ├── drawable-mdpi
│ ├── chatwindow_mesage_left.9.png
│ ├── chatwindow_message_right.9.png
│ └── goods_upload_icon.png
│ ├── drawable-v24
│ ├── user_detail.png
│ ├── user_email.png
│ ├── user_phone.png
│ └── user_user.png
│ ├── drawable-xhdpi
│ ├── chatwindow_mesage_left.9.png
│ ├── chatwindow_message_right.9.png
│ └── goods_upload_icon.png
│ ├── drawable-xxhdpi
│ ├── chatwindow_mesage_left.9.png
│ ├── chatwindow_message_right.9.png
│ └── goods_upload_icon.png
│ ├── drawable-xxxhdpi
│ ├── chatwindow_mesage_left.9.png
│ └── chatwindow_message_right.9.png
│ ├── drawable
│ ├── back.png
│ ├── background.jpg
│ ├── chatwindow_mesage_left.9.png
│ ├── chatwindow_message_right.9.png
│ ├── close.png
│ ├── dark_gray.xml
│ ├── divider.xml
│ ├── ic_arrow_upward_black_24dp.xml
│ ├── ic_camera.xml
│ ├── ic_comment_message.xml
│ ├── ic_community_comment.png
│ ├── ic_community_in.png
│ ├── ic_community_like_in.png
│ ├── ic_community_like_side.png
│ ├── ic_community_share_side.png
│ ├── ic_community_side.png
│ ├── ic_contacts_black_24dp.xml
│ ├── ic_goods_details.xml
│ ├── ic_goods_kinds.xml
│ ├── ic_goods_location.xml
│ ├── ic_goods_name.xml
│ ├── ic_launcher_background.xml
│ ├── ic_main_publish_new_community.xml
│ ├── ic_main_publish_new_goods.xml
│ ├── ic_mygoods_box.png
│ ├── ic_photo.xml
│ ├── ic_school.png
│ ├── ic_school_black_24dp.xml
│ ├── ic_search_black_24dp.xml
│ ├── ic_talk_notalk.xml
│ ├── item_selector.xml
│ ├── login_logo.png
│ ├── login_shape_user_rectangle.xml
│ ├── main_community_btn_selector.xml
│ ├── main_goods_btn_selector.xml
│ ├── main_goods_in.png
│ ├── main_goods_side.png
│ ├── main_ic_search_grey_24dp.xml
│ ├── main_ic_search_white_24dp.xml
│ ├── main_icon.png
│ ├── main_index_search.png
│ ├── main_my_btn_selector.xml
│ ├── main_my_in.png
│ ├── main_my_side.png
│ ├── main_publish.png
│ ├── main_shape_search_rectangle.xml
│ ├── main_talk_btn_selector.xml
│ ├── main_talk_in.png
│ ├── main_talk_side.png
│ ├── main_text_color_selector.xml
│ ├── my_data.png
│ ├── my_mygoods.png
│ ├── my_settings.png
│ ├── photo_select.png
│ ├── red.xml
│ ├── trash.png
│ ├── trash2.png
│ ├── user_default_0.png
│ ├── user_default_1.png
│ ├── user_detail.png
│ ├── user_email.png
│ ├── user_no.png
│ ├── user_phone.png
│ ├── user_user.png
│ ├── welcome_pic.png
│ └── white.xml
│ ├── layout
│ ├── activity_publish_article.xml
│ ├── chat_window_act.xml
│ ├── chat_window_msg_item.xml
│ ├── common_goods_recycle_item.xml
│ ├── community_comment_include.xml
│ ├── community_detail_comment_item.xml
│ ├── goods_detail_act.xml
│ ├── goods_detail_comment_item.xml
│ ├── goods_detail_review_include.xml
│ ├── goods_detail_seller_include.xml
│ ├── goods_search_act.xml
│ ├── goods_search_include.xml
│ ├── goods_upload_act.xml
│ ├── image_browser_act.xml
│ ├── login_act.xml
│ ├── main_act.xml
│ ├── main_chat_list_contacts_item.xml
│ ├── main_chat_list_frag.xml
│ ├── main_community_article_content_activity.xml
│ ├── main_community_frag.xml
│ ├── main_community_frag_recycler_view_item.xml
│ ├── main_goods_upload_frag.xml
│ ├── main_index_frag.xml
│ ├── main_index_viewpager_item.xml
│ ├── main_my_infor_frag.xml
│ ├── my_goods_act.xml
│ ├── my_goods_recycle_item.xml
│ ├── refresh_footer.xml
│ ├── register_act.xml
│ ├── settings_act.xml
│ ├── user_info_act.xml
│ ├── user_info_this_act.xml
│ ├── user_info_this_edit_act.xml
│ ├── user_info_this_pop_show_dialog.xml
│ ├── web_client_act.xml
│ └── welcome_act.xml
│ ├── menu
│ ├── common_action_bar.xml
│ └── goods_detail_action_bar.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── values-v27
│ └── styles.xml
│ ├── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── goods_categories.xml
│ ├── strings.xml
│ └── styles.xml
│ └── xml
│ └── file_paths.xml
├── bash.exe.stackdump
├── build.gradle
├── d
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 | /.idea
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # 前言
4 | 本项目做的是一个校园信息服务平台(主要做二手交易和社区信息服务),商业价值可能也不是那么大,
所以这个项目的主要价值还是提升自己的技术能力.
5 |
App 下载地址(稳定版) :
6 |
网盘地址:
7 |
8 | ### 一、代码结构
9 | ##### Java + MVVM-DataBinding + OKHttp + LitePal (现在Model层已经换成了Kotlin)
10 |
11 | > Gson
12 |
Luban
13 |
Glide
14 |
Matisse
15 |
UCrop
16 |
PhotoView
17 |
OKHttp
18 |
DataBinding
19 |
20 |
21 |
22 |
23 | ### 二、版本
24 | #### 版本 1.0
25 | + 已经完成了基本的商品系统、用户系统、IM系统、和部份社区系统
26 |
27 | #### 版本 1.1
28 | * 引入 Retrofit2
29 | * 用Thread Pool 来管理线程
30 |
31 | #### 下一计划版本
32 | * 用软件工程的方法写出正式的开发文档。
33 | * 引入RxJava RxKotlin
34 |
35 |
36 | ### 三、功能
37 | * 商品信息管理:分类浏览、上传、修改、删除、查看我的商品、商品评论的发布和删除
38 | * 用户信息管理:注册、登录、上传头像、修改资料
39 | * IM模块:发起聊天(单聊)、消息本地储存、IM消息接收基本功能(乱序处理、断线重连)
40 | * 社区模块:动态的发布和查看
41 |
42 |
43 | ### 四、项目地址 (Android Client)
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/XML.patch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/XML.patch
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /src/androidTest
3 | /src/test
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file csName.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/main/assets/litepal.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
21 |
22 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/articlecontent/ArticleContentActivityViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.articlecontent;
2 |
3 | import android.app.Activity;
4 |
5 | import com.lfork.a98620.lfree.base.BaseViewModel;
6 | import com.lfork.a98620.lfree.data.DataSource;
7 | import com.lfork.a98620.lfree.data.community.remote.CommunityRemoteDataSource;
8 | import com.lfork.a98620.lfree.main.community.CommunityCallback;
9 |
10 | public class ArticleContentActivityViewModel extends BaseViewModel {
11 | private Activity context;
12 | private int articleId;
13 |
14 | public ArticleContentActivityViewModel(Activity context, int articleId) {
15 | this.context = context;
16 | this.articleId = articleId;
17 | }
18 |
19 | public void loadData(CommunityCallback callback, boolean isRefresh) {
20 | new Thread(new Runnable() {
21 | @Override
22 | public void run() {
23 |
24 | if (articleId != -1) {
25 | CommunityRemoteDataSource.getINSTANCE().getCommentList(new DataSource.GeneralCallback() {
26 | @Override
27 | public void succeed(Object data) {
28 | if (isRefresh) {
29 | callback.callback(data, 2);
30 | } else {
31 | callback.callback(data, 1);
32 | }
33 | }
34 |
35 | @Override
36 | public void failed(String log) {
37 | callback.callback(null, 2);
38 | }
39 | }, articleId);
40 | } else {
41 | callback.callback(null, 2);
42 | }
43 | }
44 | }).start();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/articlecontent/CommunityComment.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.articlecontent;
2 |
3 | import com.lfork.a98620.lfree.base.BaseViewModel;
4 |
5 | public class CommunityComment extends BaseViewModel {
6 | private int articleId;
7 | private String comment;
8 | private String commentTime;
9 | private int reviewerId;
10 | private String reviewer;
11 |
12 | public void setArticleId(int articleId) {
13 | this.articleId = articleId;
14 | }
15 |
16 | public void setComment(String comment) {
17 | this.comment = comment;
18 | }
19 |
20 | public void setCommentTime(String commentTime) {
21 | this.commentTime = commentTime;
22 | }
23 |
24 | public void setReviewerId(int reviewerID) {
25 | this.reviewerId = reviewerID;
26 | }
27 |
28 | public int getArticleId() {
29 | return articleId;
30 | }
31 |
32 | public String getComment() {
33 | return comment;
34 | }
35 |
36 | public String getCommentTime() {
37 | return commentTime;
38 | }
39 |
40 | public int getReviewerId() {
41 | return reviewerId;
42 | }
43 |
44 | public String getReviewer() {
45 | return reviewer;
46 | }
47 |
48 | public void setReviewer(String reviewer) {
49 | this.reviewer = reviewer;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/articlecontent/CommunityCommentAdapter.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.articlecontent;
2 |
3 | import android.databinding.DataBindingUtil;
4 | import android.databinding.ViewDataBinding;
5 | import android.support.annotation.NonNull;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.view.LayoutInflater;
8 | import android.view.ViewGroup;
9 |
10 | import com.lfork.a98620.lfree.BR;
11 | import com.lfork.a98620.lfree.R;
12 |
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 |
17 | public class CommunityCommentAdapter extends RecyclerView.Adapter {
18 |
19 | private List viewModelList = new ArrayList<>();
20 |
21 | public CommunityCommentAdapter(List viewModelList) {
22 | this.viewModelList = viewModelList;
23 | }
24 |
25 | @NonNull
26 | @Override
27 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
28 | return ViewHolder.create(LayoutInflater.from(parent.getContext()), parent, viewType);
29 | }
30 |
31 | @Override
32 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
33 | holder.bindTo(viewModelList.get(position));
34 | }
35 |
36 | @Override
37 | public int getItemCount() {
38 | return viewModelList.size();
39 | }
40 |
41 | static class ViewHolder extends RecyclerView.ViewHolder {
42 |
43 | ViewDataBinding binding;
44 |
45 | ViewHolder(ViewDataBinding binding) {
46 | super(binding.getRoot());
47 | this.binding = binding;
48 | }
49 |
50 | static ViewHolder create(LayoutInflater inflater, ViewGroup parent, int type) {
51 | ViewDataBinding binding = DataBindingUtil.inflate(inflater, R.layout.community_detail_comment_item, parent, false);
52 | return new ViewHolder(binding);
53 | }
54 |
55 | void bindTo(CommunityComment itemViewModel) {
56 | binding.setVariable(BR.viewModel, itemViewModel);
57 | binding.executePendingBindings();
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/articlecontent/LightTextView.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.articlecontent;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.LinearGradient;
7 | import android.graphics.Matrix;
8 | import android.graphics.Paint;
9 | import android.graphics.Shader;
10 | import android.support.v7.widget.AppCompatTextView;
11 | import android.util.AttributeSet;
12 |
13 | public class LightTextView extends AppCompatTextView {
14 | private int mViewWidth;
15 | private Paint mPaint;
16 | private LinearGradient mLinearGradient;
17 | private Matrix mGradientMatrix;
18 | private int mTranslate;
19 |
20 | public LightTextView(Context context)
21 | {
22 | super(context);
23 | }
24 |
25 | /**
26 | * 自定义TextView,一定要有这个构造方法
27 | * @param context
28 | * @param attrs
29 | */
30 | public LightTextView(Context context, AttributeSet attrs)
31 | {
32 | super(context, attrs);
33 | }
34 |
35 | @Override
36 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
37 |
38 | super.onSizeChanged(w, h, oldw, oldh);
39 | if (mViewWidth == 0){
40 | mViewWidth = getMeasuredWidth();
41 | if (mViewWidth > 0){
42 | mPaint = getPaint();
43 | mLinearGradient = new LinearGradient(
44 | 0,
45 | 0,
46 | mViewWidth,
47 | 0,
48 | new int[]{ Color.BLUE, 0xffffffff, Color.BLUE },
49 | null, Shader.TileMode.CLAMP
50 | );
51 | mPaint.setShader(mLinearGradient);
52 | mGradientMatrix = new Matrix();
53 | }
54 | }
55 | }
56 |
57 | @Override
58 | protected void onDraw(Canvas canvas) {
59 | super.onDraw(canvas);
60 | if (mGradientMatrix != null){
61 | mTranslate += mViewWidth/5;
62 | if (mTranslate > 2*mViewWidth){
63 | mTranslate = -mViewWidth;
64 | }
65 | mGradientMatrix.setTranslate(mTranslate, 0);
66 | mLinearGradient.setLocalMatrix(mGradientMatrix);
67 | postInvalidateDelayed(100);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.util.Log;
7 |
8 | /**
9 | * Created by 98620 on 2018/3/19.
10 | */
11 |
12 | public abstract class BaseActivity extends AppCompatActivity {
13 | @Override
14 | protected void onCreate(@Nullable Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | Log.d("当前的activity的名称:", getClass().getName());
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/BaseViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base;
2 |
3 | import android.content.Context;
4 | import android.databinding.BaseObservable;
5 | import android.databinding.ObservableBoolean;
6 | import android.support.annotation.CallSuper;
7 |
8 | import com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator;
9 |
10 | /**
11 | * Created by 98620 on 2018/3/19.
12 | */
13 |
14 | public abstract class BaseViewModel extends BaseObservable {
15 |
16 | public final ObservableBoolean dataIsLoading = new ObservableBoolean(true);
17 |
18 | public final ObservableBoolean dataIsEmpty = new ObservableBoolean(false);
19 |
20 | private Context context;
21 |
22 | private ViewModelNavigator navigator;
23 |
24 | public void start() {
25 | }
26 |
27 | /**
28 | * 释放掉一些东西,防止内存泄漏
29 | */
30 | @CallSuper
31 | public void onDestroy() {
32 | navigator = null;
33 | }
34 |
35 | public BaseViewModel() {
36 | }
37 |
38 | public BaseViewModel(Context context) {
39 | this.context = context.getApplicationContext(); //force to use application context, avoid potential memory leak
40 | }
41 |
42 | public Context getContext() {
43 | return context;
44 | }
45 |
46 | public void setContext(Context context) {
47 | this.context = context;
48 | }
49 |
50 | /**
51 | *
52 | * @param navigator 自定义的navigator 必须是继承自{@link ViewModelNavigator}
53 | * 否则下面会报错
54 | * 继承自{@link ViewModelNavigator} 只有一个作用 ,通用的toast操作
55 | */
56 | public void setNavigator(Object navigator){
57 | this.navigator = (ViewModelNavigator) navigator;
58 | }
59 |
60 | // public abstract void showToast(); 大部分viewModel应该都有提示的操作:Toast,SnackBar,自定义提示等等
61 | public void showToast(String msg) {
62 | if (navigator != null) {
63 | navigator.showToast(msg);
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/Config.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base;
2 |
3 | /**
4 | * Created by 98620 on 2018/4/7.
5 | */
6 |
7 | public class Config {
8 | public static String ServerURL = "http://www.lfork.top";
9 |
10 | public static String BaseURL = "http://www.lfork.top/";
11 |
12 | public static String ServerImagePathRoot = "http://www.lfork.top/image/";
13 |
14 | public static String ServerURLTest = "http://www.lfork.top";
15 |
16 | public final static int BASE_THREAD_POOL_SIZE = 10;
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/FreeApplication.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Application;
5 | import android.content.Context;
6 |
7 | import org.litepal.LitePal;
8 |
9 | import java.util.concurrent.ExecutorService;
10 | import java.util.concurrent.Executors;
11 | import java.util.concurrent.LinkedBlockingDeque;
12 | import java.util.concurrent.ThreadPoolExecutor;
13 | import java.util.concurrent.TimeUnit;
14 |
15 | /**
16 | * Created by 98620 on 2018/3/19.
17 | */
18 |
19 | public class FreeApplication extends Application implements MyApplication {
20 |
21 | public final static String APP_SHARED_PREF = "application_shared_pref";
22 |
23 | private static ExecutorService executorService;
24 |
25 | /**
26 | * 这里因为是application context 所以就没有内存泄漏的问题,
27 | * 因为application的生命周期是最长的
28 | * application是最后被jvm释放掉的
29 | */
30 | @SuppressLint("StaticFieldLeak")
31 | private static Context context;
32 |
33 | @Override
34 | public void onCreate() {
35 | super.onCreate();
36 | context = getApplicationContext();
37 | initDataBase();
38 | initThreadPool();
39 | }
40 |
41 | @Override
42 | public void initDataBase() {
43 | LitePal.initialize(context);
44 | }
45 |
46 | public static Context getContext() {
47 | return context;
48 | }
49 |
50 | public static void setContext(Context context) {
51 | FreeApplication.context = context;
52 | }
53 |
54 |
55 | /**
56 | *
57 | */
58 | @Override
59 | public void initThreadPool() {
60 | executorService = new ThreadPoolExecutor(
61 | Config.BASE_THREAD_POOL_SIZE,
62 | Config.BASE_THREAD_POOL_SIZE * 2,
63 | 0L,
64 | TimeUnit.MICROSECONDS,
65 | new LinkedBlockingDeque<>(),
66 | Executors.defaultThreadFactory());
67 | }
68 |
69 | public static ExecutorService getAppFixedThreadPool() {
70 | return executorService;
71 | }
72 |
73 | public static ExecutorService getDefaultThreadPool() {
74 | return executorService;
75 | }
76 |
77 | public static void executeThreadInDefaultThreadPool(Runnable r) {
78 | executorService.execute(r);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/MyApplication.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base;
2 |
3 | /**
4 | *
5 | * @author 98620
6 | * @date 2018/7/16
7 | */
8 | public interface MyApplication {
9 |
10 | /**
11 | * 初始化当前应用(进程)的线程池
12 | */
13 | void initThreadPool();
14 |
15 |
16 | /**
17 | * 初始化数据库
18 | */
19 | void initDataBase();
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/bindingadapter/ListBinding.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base.bindingadapter;
2 |
3 | import android.databinding.BindingAdapter;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.widget.ListView;
6 |
7 | import com.lfork.a98620.lfree.base.adapter.ListViewAdapter;
8 | import com.lfork.a98620.lfree.base.adapter.RecyclerViewItemAdapter;
9 |
10 | import java.util.ArrayList;
11 |
12 | /**
13 | * 通用的 ListView和RecyclerView的数据绑定
14 | * Created by 98620 on 2018/6/24.
15 | */
16 | public class ListBinding {
17 |
18 | /**
19 | * 这个方法只适合一般需求的listView ,
20 | * 并且adapter是用的通用adapter {@link com.lfork.a98620.lfree.base.adapter.ListViewAdapter}
21 | *
22 | * @param listView listView
23 | * @param viewModels 各种类型的viewModel
24 | */
25 | @BindingAdapter({"setListViewItems"})
26 | public static void refreshListView(ListView listView, ArrayList viewModels) {
27 | ListViewAdapter adapter = (ListViewAdapter) listView.getAdapter();
28 | if (viewModels == null) {
29 | return;
30 | }
31 | if (adapter != null) {
32 | adapter.setItems(viewModels);
33 | adapter.notifyDataSetChanged();
34 | }
35 | }
36 |
37 | @BindingAdapter({"setRecyclerViewItems"})
38 | public static void refreshRecyclerView(RecyclerView listView, ArrayList viewModels) {
39 | RecyclerViewItemAdapter adapter = (RecyclerViewItemAdapter) listView.getAdapter();
40 | if (viewModels == null) {
41 | return;
42 | }
43 | if (adapter != null) {
44 | adapter.setItems(viewModels);
45 | adapter.notifyDataSetChanged();
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/customview/PopupDialogOnclickListener.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base.customview;
2 |
3 | /**
4 | * Created by 98620 on 2018/4/14.
5 | */
6 |
7 | public interface PopupDialogOnclickListener {
8 |
9 | void onFirstButtonClicked(PopupDialog dialog);
10 |
11 | void onSecondButtonClicked(PopupDialog dialog);
12 |
13 | void onCanceledClicked(PopupDialog dialog);
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/customview/RefreshFooterView.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base.customview;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.Nullable;
5 | import android.util.AttributeSet;
6 | import android.view.LayoutInflater;
7 | import android.widget.LinearLayout;
8 |
9 | import com.lfork.a98620.lfree.R;
10 |
11 |
12 | /**
13 | * Created by 98620 on 2018/5/5. recyclerView或是ListView下拉刷新时的页脚
14 | */
15 | public class RefreshFooterView extends LinearLayout {
16 | public RefreshFooterView(Context context, @Nullable AttributeSet attrs) {
17 | super(context, attrs);
18 | LayoutInflater.from (context) . inflate (R.layout.refresh_footer, this);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/image/GlideEngine.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base.image;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.net.Uri;
6 | import android.widget.ImageView;
7 |
8 | import com.lfork.a98620.lfree.base.bindingadapter.ImageBinding;
9 | import com.zhihu.matisse.engine.ImageEngine;
10 |
11 | /**
12 | * Created by 98620 on 2018/4/14.
13 | */
14 |
15 |
16 | public class GlideEngine implements ImageEngine {
17 |
18 | @Override
19 | public void loadThumbnail(Context context, int resize, Drawable placeholder, ImageView imageView, Uri uri) {
20 | setImage(imageView, uri);
21 | }
22 |
23 | @Override
24 | public void loadAnimatedGifThumbnail(Context context, int resize, Drawable placeholder, ImageView imageView, Uri uri) {
25 | setImage(imageView, uri);
26 | }
27 |
28 | @Override
29 | public void loadImage(Context context, int resizeX, int resizeY, ImageView imageView, Uri uri) {
30 | setImage(imageView, uri);
31 | }
32 |
33 | @Override
34 | public void loadAnimatedGifImage(Context context, int resizeX, int resizeY, ImageView imageView, Uri uri) {
35 | setImage(imageView, uri);
36 | }
37 |
38 | private void setImage(ImageView imageView, Uri uri){
39 | ImageBinding.setImageWithDiskCache(imageView, uri);
40 | }
41 |
42 |
43 | @Override
44 | public boolean supportAnimatedGif() {
45 | return true;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/image/GlideImageLoader.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base.image;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.widget.ImageView;
6 |
7 | import com.lfork.a98620.lfree.base.bindingadapter.ImageBinding;
8 | import com.youth.banner.loader.ImageLoader;
9 |
10 | public class GlideImageLoader extends ImageLoader {
11 | @Override
12 | public void displayImage(Context context, Object path, ImageView imageView) {
13 | //Glide 加载图片简单用法
14 | if (isValidContextForGlide(context))
15 | ImageBinding.setImageNoCache(imageView, path);
16 | }
17 |
18 | // final Context context = getContext();
19 | //if (isValidContextForGlide(context) {
20 | // // Load image via Glide lib using context
21 | // }
22 |
23 | private static boolean isValidContextForGlide(final Context context) {
24 | if (context == null) {
25 | return false;
26 | }
27 | if (context instanceof Activity) {
28 | final Activity activity = (Activity) context;
29 | return !activity.isDestroyed() && !activity.isFinishing();
30 | }
31 | return true;
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/image/ImageTool.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base.image;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.os.Build;
6 | import android.renderscript.Allocation;
7 | import android.renderscript.Element;
8 | import android.renderscript.RenderScript;
9 | import android.renderscript.ScriptIntrinsicBlur;
10 | import android.support.annotation.RequiresApi;
11 | import android.util.Log;
12 |
13 | /**
14 | * Created by 98620 on 2018/1/21.
15 | */
16 |
17 | public class ImageTool {
18 |
19 | private static final String TAG = "ImageTool";
20 |
21 | /**
22 | * 图片高斯化处理
23 | */
24 | @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
25 | public static Bitmap rsBlur(Context context, Bitmap source, int radius){
26 |
27 | if (source == null) {
28 | return null;
29 | }
30 | //(1)
31 | RenderScript renderScript = RenderScript.create(context);
32 |
33 | Log.i(TAG,"scale size:"+ source.getWidth()+"*"+ source.getHeight());
34 |
35 | // Allocate memory for Renderscript to work with
36 | //(2)
37 | final Allocation input = Allocation.createFromBitmap(renderScript, source);
38 | final Allocation output = Allocation.createTyped(renderScript,input.getType());
39 | //(3)
40 | // Load up an instance of the specific script that we want to use.
41 | ScriptIntrinsicBlur scriptIntrinsicBlur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));
42 | //(4)
43 | scriptIntrinsicBlur.setInput(input);
44 | //(5)
45 | // Set the blur radius
46 | scriptIntrinsicBlur.setRadius(radius);
47 | //(6)
48 | // Start the ScriptIntrinisicBlur
49 | scriptIntrinsicBlur.forEach(output);
50 | //(7)
51 | // Copy the output to the blurred bitmap
52 | output.copyTo(source);
53 | //(8)
54 | renderScript.destroy();
55 | return source;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/network/MyRetrofitCallBack.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base.network
2 |
3 | import com.lfork.a98620.lfree.data.DataSource
4 | import retrofit2.Call
5 | import retrofit2.Callback
6 | import retrofit2.Response
7 |
8 | /**
9 | *
10 | * Created by 98620 on 2018/9/12.
11 | *
12 | *
13 | */
14 | class MyRetrofitCallBack(private val generalCallback: DataSource.GeneralCallback) : Callback> {
15 | override fun onFailure(call: Call>, t: Throwable) {
16 | generalCallback.failed("error:服务器异常、或者是没有网络连接")
17 | }
18 |
19 | override fun onResponse(call: Call>, response: Response>) {
20 | Result.deal(response.body() as Result, generalCallback)
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/network/Result.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base.network
2 |
3 | import com.google.gson.annotations.SerializedName
4 | import com.lfork.a98620.lfree.data.DataSource
5 |
6 | /**
7 | *
8 | * Created by 98620 on 2018/9/12.
9 | */
10 |
11 | /**
12 | * 对服务器返回结果的进行JSON封装处理
13 | * @author 98620
14 | */
15 | class Result {
16 |
17 | @SerializedName("id")
18 | var code: Int = 0
19 |
20 | @SerializedName("msg")
21 | var message: String? = null
22 |
23 | var data: T? = null
24 |
25 | companion object {
26 | fun deal(result: Result?, callback: DataSource.GeneralCallback) {
27 | if (result != null) {
28 | val u = result.data
29 | if (u != null) {
30 | callback.succeed(u)
31 | } else {
32 | callback.failed(result.message?:"error")
33 | }
34 | } else {
35 | callback.failed("error")
36 | }
37 | }
38 | }
39 |
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/thread/MyThreadFactory.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base.thread;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import java.util.concurrent.ThreadFactory;
6 |
7 | /**
8 | * Created by 98620 on 2018/7/16.
9 | */
10 | public class MyThreadFactory implements ThreadFactory {
11 | @Override
12 | public Thread newThread(@NonNull Runnable r) {
13 |
14 | Thread t = new Thread(r);
15 |
16 | t.setName("ThreadPool");
17 |
18 | return null;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/viewmodel/GoodsViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base.viewmodel;
2 |
3 | import android.content.Context;
4 | import android.databinding.ObservableArrayList;
5 | import android.databinding.ObservableField;
6 |
7 | import com.lfork.a98620.lfree.base.BaseViewModel;
8 | import com.lfork.a98620.lfree.data.base.entity.Goods;
9 | import com.lfork.a98620.lfree.base.Config;
10 |
11 | /**
12 | * Created by 98620 on 2018/4/14.
13 | */
14 |
15 | public abstract class GoodsViewModel extends BaseViewModel {
16 |
17 |
18 | public ObservableField imagePath = new ObservableField<>(); //封面图片
19 |
20 | public ObservableField name = new ObservableField<>();
21 |
22 | public ObservableField publishDate = new ObservableField<>();
23 |
24 | public ObservableField price = new ObservableField<>();
25 |
26 | public ObservableField originPrice = new ObservableField<>();
27 |
28 | public ObservableField description = new ObservableField<>();
29 |
30 | public ObservableField type = new ObservableField<>();
31 |
32 | public ObservableArrayList images = new ObservableArrayList<>();
33 |
34 |
35 | private int id;
36 |
37 | private int categoryId;
38 |
39 | public GoodsViewModel(Context context, Goods g, int categoryId) {
40 | this(context, g);
41 | g.setCategoryId(categoryId);
42 | this.id = g.getId();
43 | this.categoryId = categoryId;
44 | }
45 |
46 |
47 | public GoodsViewModel(Context context, Goods g) {
48 | super(context);
49 | name.set(g.getName());
50 | price.set(g.getPrice() + "元");
51 | imagePath.set(Config.ServerURL + "/image" + g.getCoverImagePath());
52 | publishDate.set(g.getPublishDate());
53 | id = g.getId();
54 | categoryId = g.getCategoryId();
55 | }
56 |
57 | public GoodsViewModel() {
58 | }
59 |
60 | public GoodsViewModel(Context context) {
61 | super(context);
62 | }
63 |
64 |
65 | public void onClick() {
66 | }
67 |
68 | ;
69 |
70 | public int getId() {
71 | return id;
72 | }
73 |
74 | public void setId(int id) {
75 | this.id = id;
76 | }
77 |
78 | public int getCategoryId() {
79 | return categoryId;
80 | }
81 |
82 | public void setCategoryId(int categoryId) {
83 | this.categoryId = categoryId;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/viewmodel/UserViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base.viewmodel;
2 |
3 | import android.content.Context;
4 | import android.databinding.ObservableField;
5 |
6 | import com.lfork.a98620.lfree.base.BaseViewModel;
7 |
8 | /**
9 | * Created by 98620 on 2018/4/9.
10 | */
11 |
12 | public abstract class UserViewModel extends BaseViewModel {
13 |
14 | public final ObservableField username = new ObservableField<>();
15 |
16 | public final ObservableField description = new ObservableField<>("");
17 |
18 | public final ObservableField imageUrl = new ObservableField<>();
19 |
20 | public final ObservableField studentNumber = new ObservableField<>("");
21 |
22 | public final ObservableField phone = new ObservableField<>();
23 |
24 | public final ObservableField email = new ObservableField<>("");
25 |
26 | public final ObservableField gender = new ObservableField<>();
27 |
28 | public final ObservableField school = new ObservableField<>();
29 |
30 | public UserViewModel() {
31 | super();
32 | }
33 |
34 | public UserViewModel(Context context) {
35 | super(context);
36 |
37 | }
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/base/viewmodel/ViewModelNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.base.viewmodel;
2 |
3 | /**
4 | * Created by 98620 on 2018/4/25.
5 | *
6 | * navigator
7 | */
8 | public interface ViewModelNavigator {
9 |
10 | //大部分ViewModel 应该都有一个Toast的操作:不管是测试也好还是提示用户也行
11 | //I consider that most viewModels all have a need to send a Toast, for testing or giving tips to user
12 | void showToast(String msg);
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/chatwindow/ChatWindowNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.chatwindow;
2 |
3 | import com.lfork.a98620.lfree.data.DataSource;
4 | import com.lfork.a98620.lfree.imservice.message.Message;
5 |
6 | /**
7 | * Created by 98620 on 2018/4/22.
8 | */
9 | public interface ChatWindowNavigator {
10 | void sendMessage(Message message, DataSource.GeneralCallback callback);
11 |
12 |
13 | void showToast(String content);
14 |
15 | void notifyMessagesChanged();
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/chatwindow/MessageListAdapter.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.chatwindow;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.LinearLayout;
9 | import android.widget.TextView;
10 |
11 | import com.lfork.a98620.lfree.R;
12 | import com.lfork.a98620.lfree.imservice.message.Message;
13 |
14 | import java.util.List;
15 |
16 | ///**
17 | // * Created by 98620 on 2017/7/25.
18 | // */
19 |
20 |
21 | class MessageListAdapter extends RecyclerView.Adapter {
22 | private static final String TAG="MessageListAdapter";
23 | private List mMessageList;
24 |
25 | class ViewHolder extends RecyclerView.ViewHolder {
26 | TextView msgView_sent, msgView_rec;
27 | LinearLayout msgView_sent_parent, msgView_rec_parent;
28 |
29 | ViewHolder(View view) {
30 | super(view);
31 | msgView_rec = view.findViewById(R.id.message_rec);
32 | msgView_rec_parent = view.findViewById(R.id.message_rec_parent);
33 | msgView_sent = view.findViewById(R.id.message_sent);
34 | msgView_sent_parent = view.findViewById(R.id.message_sent_parent);
35 | }
36 | }
37 |
38 | MessageListAdapter(List messageList) {
39 | mMessageList = messageList;
40 | }
41 |
42 | //对于listView的点击事件, 只能设置item的点击事件, 不能设置item的子项的点击事件
43 |
44 | @NonNull
45 | @Override
46 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
47 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_window_msg_item, parent, false);
48 | return new ViewHolder(view);
49 | }
50 |
51 | @Override
52 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
53 | Message message = mMessageList.get(position);
54 | if (message.getChatType() == Message.ReceiveType) {
55 |
56 | //奇怪的操作 如果这里不设置隐藏属性的话 下面有些地方就会自动的跳出某些内容~~~~ 可是这些隐藏的属性我是默认就设置好了的呀
57 | holder.msgView_rec_parent.setVisibility(View.VISIBLE);
58 | holder.msgView_sent_parent.setVisibility(View.GONE);
59 | holder.msgView_rec.setText(message.getContent());
60 | } else {
61 | holder.msgView_rec_parent.setVisibility(View.GONE);
62 | holder.msgView_sent_parent.setVisibility(View.VISIBLE);
63 | holder.msgView_sent.setText(message.getContent());
64 |
65 | }
66 |
67 | }
68 |
69 | @Override
70 | public int getItemCount() {
71 | return mMessageList.size();
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/DataSource.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data
2 |
3 | /**
4 | *
5 | * Created by 98620 on 2018/8/30.
6 | */
7 | interface DataSource {
8 | interface GeneralCallback {
9 | fun succeed(data: T)
10 | fun failed(log: String)
11 | }
12 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/base/api/CommunityApi.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.base.api
2 |
3 | /**
4 | *
5 | * Created by 98620 on 2018/9/11.
6 | */
7 | interface CommunityApi {
8 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/base/api/GoodsApi.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.base.api
2 |
3 | import android.util.Log
4 | import com.google.gson.reflect.TypeToken
5 | import com.lfork.a98620.lfree.base.Config
6 | import com.lfork.a98620.lfree.base.network.HttpService
7 | import com.lfork.a98620.lfree.base.network.Result
8 | import com.lfork.a98620.lfree.data.DataSource
9 | import com.lfork.a98620.lfree.data.base.entity.*
10 | import com.lfork.a98620.lfree.data.goods.remote.GoodsRemoteDataSource
11 | import com.lfork.a98620.lfree.util.JSONUtil
12 | import okhttp3.FormBody
13 | import okhttp3.MediaType
14 | import okhttp3.MultipartBody
15 | import okhttp3.RequestBody
16 | import retrofit2.Call
17 | import retrofit2.http.*
18 | import java.io.File
19 | import java.util.ArrayList
20 |
21 | /**
22 | *
23 | * Created by 98620 on 2018/9/11.
24 | */
25 | interface GoodsApi {
26 |
27 | /**
28 | * 根据商品的种类和当前页面的用于定位的时间信息 @param cursor 来查询商品信息
29 | *
30 | * @param categoryId 商品种类id
31 | * @param cursor 当前显示商品的游标位置(商品的时间信息)
32 | * @return 返回的查询结果
33 | */
34 | @GET("22y/goodsApp_getGoodsPageApp")
35 | fun getGoodsList(@Query("csId") categoryId: Int, @Query("cursor") cursor: String): Call>>
36 |
37 |
38 | @GET("22y/user_getUserGoodsByUid")
39 | fun getUserGoodsList(@Query("studentId") userId: String, @Query("cursor") cursor: String): Call>>
40 |
41 |
42 | @GET("22y/cs_getCsList")
43 | fun getUserGoodsList(): Call>>
44 |
45 |
46 | @GET("22y/goods_getGoodsById")
47 | fun getGoods(@Query("goodsId") goodsId: String): Call>
48 |
49 |
50 | @GET("22y/goodsSerach_getGoodsByName")
51 | fun goodsSearch(@Query("goodsLikeName") keyword: String): Call>>
52 |
53 |
54 | /**
55 | * 添加商品评论
56 | *
57 | * @param username studentId,email,username都行
58 | * @param password 密码
59 | * @return 指定请求数据的Call对象
60 | */
61 | @FormUrlEncoded
62 | @POST("22y/review_reviewSave")
63 | fun addReview(
64 | @Field("userId") userId: String,
65 | @Field("goodsId") goodsId: String,
66 | @Field("reviewContext") content: String): Call>
67 |
68 |
69 | /**
70 | * 更新用户头像 单文件上传实例
71 | * Part的普通键值对需要用RequestBody来写
72 | * RequestBody.create(null, studentId)
73 | * @param fileBody .
74 | * @param studentId .
75 | * @return .
76 | */
77 | @POST("22y/goods_upload")
78 | fun uploadGoods(@Body multipartBody: MultipartBody): Call>
79 |
80 |
81 | companion object {
82 | fun create(): GoodsApi {
83 | val retrofit = HttpService.getRetrofitInstance()
84 | return retrofit.create(GoodsApi::class.java)
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/base/api/UserApi.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.base.api
2 |
3 | import com.lfork.a98620.lfree.base.network.HttpService
4 | import com.lfork.a98620.lfree.base.network.Result
5 | import com.lfork.a98620.lfree.data.base.entity.User
6 | import okhttp3.MultipartBody
7 | import okhttp3.RequestBody
8 | import retrofit2.Call
9 | import retrofit2.http.*
10 |
11 | /**
12 | *
13 | * Created by 98620 on 2018/8/26.
14 | */
15 | interface UserApi {
16 |
17 | /**
18 | * 用户登录
19 | *
20 | * @param username studentId,email,username都行
21 | * @param password 密码
22 | * @return 指定请求数据的Call对象
23 | */
24 | @FormUrlEncoded
25 | @POST("22y/user_login")
26 | fun login(
27 | @Field("studentId") username: String,
28 | @Field("userPassword") password: String): Call>
29 |
30 |
31 | /**
32 | * 用户注册
33 | *
34 | * @param studentId .
35 | * @param password .
36 | * @param username .
37 | * @param schoolId .
38 | * @return 指定请求数据的Call对象
39 | */
40 | @FormUrlEncoded
41 | @POST("22y/user_regist")
42 | fun register(
43 | @Field("studentId") studentId: String,
44 | @Field("userPassword") password: String,
45 | @Field("userName") username: String,
46 | @Field("userSchool.id") schoolId: String): Call>
47 |
48 | /**
49 | * 根据Id获取用户的完整信息
50 | *
51 | * @param userId .
52 | * @return .
53 | */
54 | @GET("22y/user_info")
55 | fun getUserInfo(@Query("studentId") userId: String): Call>
56 |
57 |
58 | /**
59 | * 更新用户头像 单文件上传实例
60 | * Part的普通键值对需要用RequestBody来写
61 | * RequestBody.create(null, studentId)
62 | * @param fileBody .
63 | * @param studentId .
64 | * @return .
65 | */
66 | @Multipart
67 | @POST("22y/user_imageUpload")
68 | fun updatePortrait(
69 | @Part fileBody: MultipartBody.Part,
70 | @Part("studentId") studentId: RequestBody): Call>
71 |
72 | /**
73 | * @param studentId .
74 | * @param username .
75 | * @param schoolId .
76 | * @param dec .
77 | * @param email .
78 | * @param phone .
79 | * @return .
80 | */
81 | @FormUrlEncoded
82 | @POST("22y/user_save")
83 | fun updateUserInfo(
84 | @Field("studentId") studentId: Int,
85 | @Field("userName") username: String,
86 | @Field("userSchool.id") schoolId: String,
87 | @Field("userDesc") dec: String,
88 | @Field("userEmail") email: String,
89 | @Field("userPhone") phone: String
90 | ): Call>
91 |
92 | companion object {
93 | fun create() : UserApi {
94 | val retrofit = HttpService.getRetrofitInstance()
95 | return retrofit.create(UserApi::class.java)
96 | }
97 | }
98 |
99 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/base/entity/Category.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.base.entity
2 |
3 | import org.litepal.crud.DataSupport
4 | import java.io.Serializable
5 |
6 | /**
7 | * Created by 98620 on 2018/4/7.
8 | */
9 |
10 | data class Category(val id: Int, val csId: Int, var csName: String?) : DataSupport(), Serializable
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/base/entity/Goods.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.base.entity
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | import java.io.Serializable
6 |
7 | /**
8 | *
9 | * Created by 98620 on 2018/3/31.
10 | */
11 |
12 | open class Goods : Serializable {
13 | @SerializedName("gName")
14 | var name: String? = null
15 |
16 | @SerializedName("gId")
17 | var id: Int = 0
18 |
19 | @SerializedName("gBuyPrice")
20 | var originPrice: String? = null
21 |
22 | @SerializedName("gSellPrice")
23 | var price: String? = null
24 |
25 | @SerializedName("gCoverImage")
26 | var coverImagePath: String? = null
27 |
28 | var imagesPath: Array? = null
29 |
30 | @SerializedName("desc")
31 | var description: String? = null
32 |
33 | @SerializedName("userImage")
34 | var userPortraitPath: String? = null
35 |
36 | @SerializedName("gMakeDate")
37 | var publishDate: String? = null
38 |
39 | var userId: Int = 0
40 |
41 | var categoryId: Int = 0
42 |
43 | override fun toString(): String {
44 | return "【商品名称】:" + name +
45 | "\n【商品价格】:" + price +
46 | "\n【描述】:" + description +
47 | "\n更多详细信息,就赶快来下载L.Free吧 " +
48 | "\nhttp://www.lfork.top"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/base/entity/GoodsDetailInfo.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.base.entity
2 |
3 | import com.google.gson.annotations.SerializedName
4 | import java.util.*
5 |
6 | /**
7 | *
8 | * Created by 98620 on 2018/8/29.
9 | */
10 |
11 | class GoodsDetailInfo : Goods() {
12 |
13 | @SerializedName("username")
14 | val sellerName: String? = null
15 |
16 | val images: Array? = null
17 |
18 | val reviews: ArrayList? = null
19 |
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/base/entity/IMUser.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.base.entity
2 |
3 | /**
4 | *
5 | * Created by 98620 on 2018/8/29.
6 | */
7 | class IMUser(val id: Int) {
8 | var username: String = ""
9 | var password: String = ""
10 | override fun toString(): String {
11 | return "[{\"username\":\"$username\",\"id\":\"$id\"}]"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/base/entity/Review.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.base.entity
2 |
3 | import com.google.gson.annotations.SerializedName
4 | import java.io.Serializable
5 |
6 | /**
7 | *
8 | * Created by 98620 on 2018/8/29.
9 | */
10 | class Review(@field:SerializedName("rContent")
11 | var content: String?) : Serializable {
12 |
13 | @SerializedName("gId")
14 | var goodsId: String? = null
15 |
16 | var user: User? = null
17 |
18 | var userId: String? = null
19 |
20 | @SerializedName("rMakeDate")
21 | var time: String? = null
22 |
23 | @SerializedName("rId")
24 | var id: Int = 0
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/base/entity/School.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.base.entity
2 |
3 | /**
4 | *
5 | * Created by 98620 on 2018/8/29.
6 | */
7 | class School(val id: String, val schoolName: String = "??") {
8 | override fun toString(): String {
9 | return schoolName
10 | }
11 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/base/entity/User.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.base.entity
2 |
3 | import org.litepal.annotation.Column
4 | import org.litepal.crud.DataSupport
5 |
6 | /**
7 | *
8 | * Created by 98620 on 2018/8/29.
9 | */
10 | class User : DataSupport {
11 | var id: Int = 0 //储存在本地数据库里面的id
12 |
13 | @Column(unique = true, defaultValue = "unknown") //啊啊啊
14 | var userId: Int = 0 //用户的ID
15 |
16 | var studentId: String? = null //userId == studentId
17 |
18 | var userName: String? = null //用户姓名
19 |
20 | var userPassword: String? = null //用户密码
21 |
22 | var userEmail: String? = null //用户邮箱地址
23 |
24 | var userPhone: String? = null //用户电话号码
25 |
26 | var userAddress: String? = null //用户的住址
27 |
28 | var userImagePath: String? = null //用户头像文件存放路径
29 |
30 | var userDesc: String? = null //用户描述
31 |
32 | var userMakeDate: String? = null //用户修改或者注册时间
33 |
34 | var userSchool: School? = null
35 |
36 | var timestamp: Long = 0
37 |
38 | var isLogin: Boolean = false
39 |
40 | var isChatUser: Boolean = false
41 |
42 | constructor() {}
43 |
44 | /**
45 | * 注册的时候用
46 | */
47 | constructor(userName: String, userPassword: String, userEmail: String, userPhone: String, userAddress: String,
48 | userImagePath: String, userDesc: String, userMakeDate: String) {
49 | this.userName = userName
50 | this.userPassword = userPassword
51 | this.userEmail = userEmail
52 | this.userPhone = userPhone
53 | this.userAddress = userAddress
54 | this.userImagePath = userImagePath
55 | this.userDesc = userDesc
56 | this.userMakeDate = userMakeDate
57 | }
58 |
59 | override fun toString(): String {
60 | return ("User [userId=" + userId + ", userName=" + userName + ", userPassword=" + userPassword + ", userEmail="
61 | + userEmail + ", userPhone=" + userPhone + ", userAddress=" + userAddress + ", userImagePath="
62 | + userImagePath + ", userDesc=" + userDesc + ", userMakeDate=" + userMakeDate + "]")
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/community/CommunityDataSource.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.community;
2 |
3 | import com.lfork.a98620.lfree.data.DataSource;
4 |
5 | public interface CommunityDataSource extends DataSource {
6 | void getArticleList(String fromTime, GeneralCallback callback);
7 | void getCommentList(GeneralCallback callback, int articleId);
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/community/local/CommunityLocalDataSource.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.community.local;
2 |
3 | import com.lfork.a98620.lfree.articlecontent.CommunityComment;
4 | import com.lfork.a98620.lfree.data.community.CommunityDataSource;
5 | import com.lfork.a98620.lfree.main.community.CommunityArticle;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | public class CommunityLocalDataSource implements CommunityDataSource {
11 |
12 | private static List articleList = new ArrayList<>();
13 |
14 | public static void setArticleList(List articleList) {
15 | if (articleList.size()!= 0) {
16 | CommunityLocalDataSource.articleList.addAll(articleList);
17 | }
18 | }
19 |
20 | public static List getArticleList() {
21 | return articleList;
22 | }
23 |
24 | @Override
25 | public void getArticleList(String fromTime, GeneralCallback callback) {}
26 |
27 | @Override
28 | public void getCommentList(GeneralCallback callback, int articleId) {}
29 |
30 | public static CommunityArticle getLocalArticle(int articlId) {
31 | CommunityArticle itemViewModel = null;
32 | for (CommunityArticle item : articleList) {
33 | if (item.getArticleId() == articlId) {
34 | itemViewModel = item;
35 | break;
36 | }
37 | }
38 | return itemViewModel;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/goods/GoodsDataSource.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.goods
2 |
3 | import com.lfork.a98620.lfree.data.DataSource
4 | import com.lfork.a98620.lfree.data.base.entity.Category
5 | import com.lfork.a98620.lfree.data.base.entity.Goods
6 | import com.lfork.a98620.lfree.data.base.entity.GoodsDetailInfo
7 | import com.lfork.a98620.lfree.data.base.entity.Review
8 |
9 | /**
10 | *
11 | * Created by 98620 on 2018/9/2.
12 | */
13 | interface GoodsDataSource : DataSource {
14 | fun getGoodsList(callback: DataSource.GeneralCallback>, cursor: String, categoryId: Int)
15 |
16 | fun getUserGoodsList(callback: DataSource.GeneralCallback>, cursor: String, userId: String)
17 |
18 | fun getCategories(callback: DataSource.GeneralCallback>)
19 |
20 | fun getGoods(callback: DataSource.GeneralCallback, goodsId: Int)
21 |
22 | fun uploadGoods(callback: DataSource.GeneralCallback, g: Goods)
23 |
24 | fun goodsSearch(callback: DataSource.GeneralCallback>, keyword: String)
25 |
26 | fun deleteGoods(callback: DataSource.GeneralCallback, goodsId: Int)
27 |
28 | fun updateGoods(callback: DataSource.GeneralCallback, g: Goods)
29 |
30 | fun addReview(callback: DataSource.GeneralCallback, review: Review)
31 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/goods/local/GoodsLocalDataSource.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.goods.local
2 |
3 | import com.lfork.a98620.lfree.data.DataSource
4 | import com.lfork.a98620.lfree.data.base.entity.Category
5 | import com.lfork.a98620.lfree.data.base.entity.Goods
6 | import com.lfork.a98620.lfree.data.base.entity.GoodsDetailInfo
7 | import com.lfork.a98620.lfree.data.base.entity.Review
8 | import com.lfork.a98620.lfree.data.goods.GoodsDataSource
9 | import org.litepal.crud.DataSupport
10 |
11 | /**
12 | *
13 | * Created by 98620 on 2018/9/2.
14 | */
15 | object GoodsLocalDataSource : GoodsDataSource {
16 | override fun getGoodsList(callback: DataSource.GeneralCallback>, cursor: String, categoryId: Int) {
17 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
18 | }
19 |
20 | override fun getUserGoodsList(callback: DataSource.GeneralCallback>, cursor: String, userId: String) {
21 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
22 | }
23 |
24 | override fun getGoods(callback: DataSource.GeneralCallback, goodsId: Int) {
25 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
26 | }
27 |
28 | override fun deleteGoods(callback: DataSource.GeneralCallback, goodsId: Int) {
29 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
30 | }
31 |
32 | override fun uploadGoods(callback: DataSource.GeneralCallback, g: Goods) {
33 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
34 | }
35 |
36 | override fun goodsSearch(callback: DataSource.GeneralCallback>, keyword: String) {
37 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
38 | }
39 |
40 | override fun updateGoods(callback: DataSource.GeneralCallback, g: Goods) {
41 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
42 | }
43 |
44 | override fun addReview(callback: DataSource.GeneralCallback, review: Review) {
45 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
46 | }
47 |
48 | fun destroyInstance() {
49 | //do nothing here
50 | }
51 |
52 | override fun getCategories(callback: DataSource.GeneralCallback>) {
53 | val categories = DataSupport.findAll(Category::class.java)
54 | if (categories != null) {
55 | callback.succeed(categories)
56 | } else {
57 | callback.failed("本地数据为空")
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/imdata/IMDataSource.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.imdata
2 |
3 | import com.lfork.a98620.lfree.data.DataSource
4 | import com.lfork.a98620.lfree.data.base.entity.User
5 | import com.lfork.a98620.lfree.imservice.request.LoginListener
6 |
7 | /**
8 | *
9 | * Created by 98620 on 2018/9/3.
10 | */
11 |
12 | interface IMDataSource : DataSource {
13 |
14 | /**
15 | * 登录成功后,客户端会马上请求用户的详细信息(当然,不包含密码)。 //TODO请求完毕后需要更新TCP本地连接的用户信息
16 | */
17 | fun login(user: User, listener: LoginListener)
18 |
19 | fun logout(userId: Int, result: DataSource.GeneralCallback)
20 |
21 | fun getChatUserList(callback: DataSource.GeneralCallback>)
22 |
23 | fun addChatUser(user: User, callback: DataSource.GeneralCallback)
24 |
25 | fun addChatUser(user: User, isExisted: Boolean, callback: DataSource.GeneralCallback)
26 |
27 | fun removeChatUser(userId: Int, callback: DataSource.GeneralCallback>)
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/imdata/MessageDataSource.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.imdata
2 |
3 | import com.lfork.a98620.lfree.data.DataSource
4 | import com.lfork.a98620.lfree.data.DataSource.GeneralCallback
5 | import com.lfork.a98620.lfree.imservice.MessageListener
6 | import com.lfork.a98620.lfree.imservice.message.Message
7 | import com.lfork.a98620.lfree.imservice.message.MessageContentType
8 |
9 | /**
10 | *
11 | * Created by 98620 on 2018/9/3.
12 | */
13 | interface MessageDataSource : DataSource {
14 |
15 | /**
16 | * 首次打开界面的时候,加载已有的Message list。
17 | * @param id 用户的id , Group的ID, 或是系统的ID
18 | * @param type [MessageContentType]
19 | * @param callback 回调
20 | */
21 | fun getMessages(id: Int, type: MessageContentType, callback: GeneralCallback>)
22 |
23 | /**
24 | * 将最新的一条消息推送到view界面 ,
25 | */
26 | fun setMessageListener(listener: MessageListener)
27 |
28 |
29 | /**
30 | * 前台把数据储存到消息仓库和消息队列, 然后再由信使从消息仓库拿走消息
31 | * local 负责储存本地消息 remote负责把消息发送到服务器
32 | * @param msg 需要发送的消息
33 | * @param callback 回调
34 | */
35 | fun saveAndSendMessage(msg: Message, callback: GeneralCallback)
36 |
37 |
38 | /**
39 | * 删除消息记录
40 | * @param id 用户的id , Group的ID, 或是系统的ID
41 | * @param type [MessageContentType]
42 | */
43 | fun clearMessages(id: Int, type: MessageContentType)
44 |
45 | //消息队列与消息仓库
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/imdata/local/IMLocalDataSource.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.imdata.local
2 |
3 | import com.lfork.a98620.lfree.data.DataSource.GeneralCallback
4 | import com.lfork.a98620.lfree.data.base.entity.User
5 | import com.lfork.a98620.lfree.data.imdata.IMDataSource
6 | import com.lfork.a98620.lfree.imservice.request.LoginListener
7 | import org.litepal.crud.DataSupport
8 |
9 | /**
10 | *
11 | * Created by 98620 on 2018/9/3.
12 | */
13 |
14 | class IMLocalDataSource : IMDataSource {
15 |
16 | /**
17 | * 伪单例、不需要线程同步、懒汉模式
18 | */
19 | companion object {
20 | private var INSTANCE: IMLocalDataSource? = null
21 | fun getInstance(): IMLocalDataSource {
22 | if (INSTANCE == null) {
23 | INSTANCE = IMLocalDataSource()
24 | }
25 | return INSTANCE as IMLocalDataSource
26 | }
27 |
28 | fun destroyInstance() {
29 | INSTANCE = null
30 | }
31 | }
32 |
33 | override fun login(user: User, listener: LoginListener) {
34 | }
35 |
36 | override fun logout(userId: Int, callback: GeneralCallback) {
37 | }
38 |
39 | override fun getChatUserList(callback: GeneralCallback>) {
40 | val userList = DataSupport.where("ischatuser=1").order("timestamp desc").find(User::class.java)
41 | if (userList != null) {
42 | callback.succeed(userList)
43 | } else {
44 | callback.failed("没有数据")
45 | }
46 | }
47 |
48 | override fun addChatUser(user: User, callback: GeneralCallback) {
49 | user.isChatUser = true
50 | user.timestamp = System.currentTimeMillis()
51 | user.save()
52 | callback.succeed("添加成功")
53 | }
54 |
55 | override fun addChatUser(user: User, isExisted: Boolean, callback: GeneralCallback) {
56 | }
57 |
58 | override fun removeChatUser(userId: Int, callback: GeneralCallback>) {
59 | DataSupport.deleteAll(User::class.java, "userid = ?", userId.toString() + "")
60 | callback.succeed(emptyList())
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/imdata/local/MessageLocalDataSource.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.imdata.local
2 |
3 | import com.lfork.a98620.lfree.data.DataSource.GeneralCallback
4 | import com.lfork.a98620.lfree.data.imdata.MessageDataSource
5 | import com.lfork.a98620.lfree.imservice.MessageListener
6 | import com.lfork.a98620.lfree.imservice.message.Message
7 | import com.lfork.a98620.lfree.imservice.message.MessageContentType
8 | import org.litepal.crud.DataSupport
9 | import org.litepal.crud.callback.FindMultiCallback
10 |
11 | /**
12 | *
13 | * Created by 98620 on 2018/9/3.
14 | */
15 | class MessageLocalDataSource : MessageDataSource {
16 |
17 | companion object {
18 | private var INSTANCE: MessageLocalDataSource? = null
19 | fun getInstance(): MessageLocalDataSource {
20 | if (INSTANCE == null) {
21 | INSTANCE = MessageLocalDataSource()
22 | }
23 | return INSTANCE as MessageLocalDataSource
24 | }
25 |
26 | fun destroyInstance() {
27 | INSTANCE = null
28 | }
29 | }
30 |
31 | override fun getMessages(id: Int, type: MessageContentType, callback: GeneralCallback>) {
32 | DataSupport.where("receiverid=? or senderid=?", id.toString() + "", id.toString() + "").order("messageID") //messageId 实际上是message生成的时间 System.currentTimeMillis()
33 | .findAsync(Message::class.java)
34 | .listen(object : FindMultiCallback {
35 | override fun onFinish(t: List) {
36 |
37 | if (t.size < 1) {
38 | callback.failed("没有消息记录")
39 | } else {
40 | callback.succeed(t as List)
41 | }
42 | }
43 | })
44 |
45 | }
46 |
47 | override fun setMessageListener(listener: MessageListener) {
48 | //消息监听交给 remote进行处理
49 | }
50 |
51 | override fun saveAndSendMessage(msg: Message, callback: GeneralCallback) {
52 | msg.saveAsync().listen { success ->
53 | if (success) {
54 | callback.succeed(Message())
55 | } else {
56 | callback.failed("消息重复")
57 | }
58 | }
59 |
60 | }
61 |
62 | override fun clearMessages(id: Int, type: MessageContentType) {
63 |
64 | }
65 |
66 |
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/user/UserDataSource.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.user
2 |
3 | import com.lfork.a98620.lfree.data.DataSource
4 | import com.lfork.a98620.lfree.data.DataSource.GeneralCallback
5 | import com.lfork.a98620.lfree.data.base.entity.School
6 | import com.lfork.a98620.lfree.data.base.entity.User
7 |
8 | /**
9 | *
10 | * Created by 98620 on 2018/8/30.
11 | */
12 | interface UserDataSource : DataSource{
13 | /**
14 | * apply an account
15 | * @param callback call back with string result
16 | * @param user user information
17 | */
18 | fun register(callback: GeneralCallback, user: User)
19 |
20 | /**
21 | * update user information
22 | * @param callback call back with string result
23 | * @param user user information
24 | */
25 | fun updateUserInfo(callback: GeneralCallback, user: User)
26 |
27 | /**
28 | * update user photo
29 | * @param callback call back with string result
30 | * @param studentId user id
31 | * @param localFilePath local file path
32 | */
33 | fun updateUserPortrait(callback: GeneralCallback, studentId: String, localFilePath: String)
34 |
35 | /**
36 | * do login
37 | * @param callback call back with User object
38 | * @param user user information
39 | */
40 | fun login(callback: GeneralCallback, user: User)
41 |
42 | /**
43 | * 获取用户信息 userId为-1的时候表示获取当前用户信息
44 | * 当前用户信息需要存放在本地数据库(只保存部份关键信息)
45 | * @param callback .
46 | * @param userId userId
47 | */
48 | fun getUserInfo(callback: GeneralCallback, userId: Int)
49 |
50 | /**
51 | * get schools information
52 | * @param callback call back with userSchool information list.
53 | */
54 | fun getSchoolList(callback: GeneralCallback>)
55 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/data/user/local/UserLocalDataSource.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.data.user.local
2 |
3 | import android.util.Log
4 | import com.lfork.a98620.lfree.data.DataSource
5 | import com.lfork.a98620.lfree.data.base.entity.School
6 | import com.lfork.a98620.lfree.data.base.entity.User
7 | import com.lfork.a98620.lfree.data.user.UserDataSource
8 | import org.litepal.crud.DataSupport
9 |
10 | /**
11 | *
12 | * Created by 98620 on 2018/8/30.
13 | */
14 | object UserLocalDataSource : UserDataSource {
15 |
16 | private val TAG = "IMRemoteDataSource"
17 |
18 | fun destroyInstance() {
19 | //do nothing here
20 | }
21 |
22 | override fun login(callback: DataSource.GeneralCallback, user: User) {}
23 |
24 | override fun register(callback: DataSource.GeneralCallback, user: User) {
25 | //do nothing here
26 | }
27 |
28 | fun getThisUser(callback: DataSource.GeneralCallback) {
29 | val userList = DataSupport.where("isLogin=?", "1").find(User::class.java)
30 | var user: User? = null
31 | if (userList != null && userList.size > 0) {
32 | user = userList[0]
33 | }
34 |
35 | if (user != null) {
36 | callback.succeed(user)
37 | } else {
38 | callback.failed("没有用户")
39 | }
40 | }
41 |
42 | fun saveThisUser(user: User): Boolean {
43 | try {
44 | DataSupport.deleteAll(User::class.java, "islogin=0 and userid=? ", user.userId.toString() + "")
45 | val result = user.save()
46 | Log.d(TAG, "saveThisUser: 用户信息本地更新成功$result")
47 | return result
48 | } catch (e: Exception) {
49 | return false
50 | }
51 |
52 | }
53 |
54 | override fun updateUserInfo(callback: DataSource.GeneralCallback, user: User) {
55 |
56 | try {
57 | DataSupport.deleteAll(User::class.java, "islogin=0 and userid=? ", user.userId.toString() + "")
58 | val result = user.save()
59 | Log.d(TAG, "saveThisUser: 用户信息本地更新成功$result")
60 | } catch (e: Exception) {
61 | }
62 |
63 | user.update(user.id.toLong())
64 | }
65 |
66 | override fun updateUserPortrait(callback: DataSource.GeneralCallback, studentId: String, localFilePath: String) {
67 |
68 | }
69 |
70 | override fun getUserInfo(callback: DataSource.GeneralCallback, userId: Int) {
71 | val list = DataSupport.where("userid=?", userId.toString() + "").find(User::class.java)
72 | if (list != null && list.size > 0) {
73 | callback.succeed(list[0])
74 | } else {
75 | callback.failed("没有数据")
76 | }
77 | }
78 |
79 | override fun getSchoolList(callback: DataSource.GeneralCallback>) {
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/goodsdetail/GoodsDetailNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.goodsdetail;
2 |
3 | import android.databinding.ObservableArrayList;
4 |
5 | import com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator;
6 |
7 | import java.util.ArrayList;
8 |
9 | /**
10 | * Created by 98620 on 2018/5/9.
11 | */
12 | public interface GoodsDetailNavigator extends ViewModelNavigator{
13 |
14 | /**
15 | * 这里主要是把View下滑到最后一行
16 | */
17 | void notifyReviewChanged();
18 |
19 | void closeSoftKeyBoard();
20 |
21 | void openUserInfo(int userId);
22 |
23 | void openChatWindow(String s, int userId);
24 |
25 | void openBigImages(ObservableArrayList images, int position);
26 |
27 | void refreshBanner(ArrayList images);
28 |
29 | void setActionBar();
30 |
31 | void shareGoods(String str);
32 |
33 | void deleteGoods(boolean succeed);
34 |
35 | void deleteReview(boolean succeed, int reviewId);
36 |
37 | void updateGoods(int goodsId);
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/goodsdetail/ReviewItemViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.goodsdetail;
2 |
3 | import android.databinding.ObservableBoolean;
4 | import android.databinding.ObservableField;
5 | import android.databinding.ObservableInt;
6 |
7 | import com.lfork.a98620.lfree.base.BaseViewModel;
8 | import com.lfork.a98620.lfree.data.base.entity.Review;
9 | import com.lfork.a98620.lfree.data.user.UserDataRepository;
10 | import com.lfork.a98620.lfree.base.Config;
11 |
12 | import java.lang.ref.WeakReference;
13 |
14 | /**
15 | * Created by 98620 on 2018/6/13.
16 | */
17 | public class ReviewItemViewModel extends BaseViewModel{
18 |
19 | public final ObservableField userPortraitPath = new ObservableField<>();
20 |
21 | public final ObservableField index = new ObservableField<>(); //review id
22 |
23 | public final ObservableField reviewerName = new ObservableField<>();
24 |
25 | public final ObservableField content = new ObservableField<>();
26 |
27 | public final ObservableField time = new ObservableField<>();
28 |
29 | public final ObservableBoolean isReviewedByThisUser = new ObservableBoolean(false);
30 |
31 | public final ObservableInt id = new ObservableInt();
32 |
33 | private WeakReference navigator ;
34 |
35 | ReviewItemViewModel(Review review, GoodsDetailNavigator navigator) {
36 | this.navigator = new WeakReference<>(navigator);
37 | userPortraitPath.set(Config.ServerURL + "/image/" + review.getUser().getUserImagePath());
38 | index.set(review.getGoodsId());
39 | reviewerName.set(review.getUser().getUserName());
40 | time.set(review.getTime());
41 | content.set(review.getContent());
42 | id.set(review.getId());
43 | int reviewerId = review.getUser().getUserId();
44 | if (reviewerId == UserDataRepository.INSTANCE.getUserId()) {
45 | isReviewedByThisUser.set(true);
46 | }
47 | }
48 |
49 |
50 | public void deleteReview(){
51 | if (navigator != null && navigator.get() != null) {
52 | navigator.get().deleteReview(true, id.get());
53 | }
54 |
55 | }
56 |
57 | @Override
58 | public void setNavigator(Object navigator) {
59 | super.setNavigator(navigator);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/goodsuploadupdate/GoodsCategoriesBinding.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.goodsuploadupdate;
2 |
3 | import android.databinding.BindingAdapter;
4 | import android.widget.ArrayAdapter;
5 | import android.widget.Spinner;
6 |
7 | import com.lfork.a98620.lfree.data.base.entity.Category;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * Created by 98620 on 2018/6/2.
13 | */
14 | public class GoodsCategoriesBinding {
15 | private static final String TAG = "GoodsListBinding";
16 | @SuppressWarnings("unchecked")
17 | @BindingAdapter("categories_items")
18 | public static void setItems(Spinner spinner, List items) {
19 | ArrayAdapter arrayAdapter = new ArrayAdapter(spinner.getContext(), android.R.layout.simple_spinner_dropdown_item, items);
20 | spinner.setAdapter(arrayAdapter);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/goodsuploadupdate/GoodsUploadUpdateNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.goodsuploadupdate;
2 |
3 | import android.net.Uri;
4 |
5 | import com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * Created by 98620 on 2018/5/28.
11 | */
12 | public interface GoodsUploadUpdateNavigator extends ViewModelNavigator {
13 | void uploadSucceed(String msg);
14 |
15 | void uploadFailed(String log);
16 |
17 | void deleteImage(int index);
18 |
19 | void showMyDialog(int count);
20 |
21 | void setDefaultCategory(int category);
22 |
23 | void setImages(List images);
24 |
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imagebrowser/ImageBrowserActivity.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imagebrowser;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v7.app.ActionBar;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.view.MenuItem;
9 |
10 | import com.github.chrisbanes.photoview.PhotoView;
11 | import com.lfork.a98620.lfree.R;
12 | import com.lfork.a98620.lfree.base.bindingadapter.ImageBinding;
13 |
14 | import java.util.ArrayList;
15 | import java.util.Objects;
16 |
17 | /**
18 | * 图片浏览器
19 | */
20 | public class ImageBrowserActivity extends AppCompatActivity {
21 |
22 |
23 | private ArrayList urls;
24 | private int position;
25 |
26 | private PhotoView photoView;
27 |
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.image_browser_act);
32 | Intent intent = getIntent();
33 | position = intent.getIntExtra("position", 0);
34 | Bundle bundle = intent.getBundleExtra("bundle");
35 | urls = bundle.getStringArrayList("urls");
36 | photoView = findViewById(R.id.big_image);
37 |
38 | if (urls != null && urls.size() > 0) {
39 | ImageBinding.setImageNoCache(photoView, urls.get(position));
40 | }
41 |
42 | setupActionBar();
43 | }
44 |
45 |
46 | private void setupActionBar(){
47 | ActionBar actionBar = getSupportActionBar();
48 | Objects.requireNonNull(actionBar).setDisplayShowTitleEnabled(true);
49 | actionBar.setTitle("原图查看");
50 | actionBar.setDisplayHomeAsUpEnabled(true); // 决定左上角图标的右侧是否有向左的小箭头, true
51 | // 有小箭头,并且图标可以点击
52 | actionBar.setDisplayShowHomeEnabled(false);
53 | }
54 |
55 | @Override
56 | public boolean onOptionsItemSelected(MenuItem item) {
57 |
58 | switch (item.getItemId()) {
59 | case android.R.id.home:
60 | finish();
61 | break;
62 | default:
63 | break;
64 | }
65 | return super.onOptionsItemSelected(item);
66 | }
67 |
68 |
69 | public static void actionStart(Context context, ArrayList urls, int position){
70 | Intent intent = new Intent(context, ImageBrowserActivity.class);
71 | Bundle bundle = new Bundle();
72 | bundle.putStringArrayList("urls", urls);
73 | intent.putExtra("bundle", bundle);
74 | intent.putExtra("position", position);
75 | context.startActivity(intent);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/Config.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice;
2 |
3 | public class Config {
4 | // public static String URL = "192.168.1.228";
5 | // public static String URL = "192.168.1.63";
6 | public static String URL = "www.lfork.top"; //
7 |
8 | private static boolean connected; //这个同tcp 的 connected保持一致
9 |
10 | public static boolean isConnected() {
11 | return connected;
12 | }
13 |
14 | public static void setConnected(boolean connected) {
15 | Config.connected = connected;
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/MessageListener.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice;
2 |
3 | ///**
4 | // * Created by 98620 on 2017/8/18.
5 | // */
6 |
7 | import com.lfork.a98620.lfree.imservice.message.Message;
8 |
9 | public interface MessageListener {
10 | void onReceived(Message message);
11 | // void onSuccess();
12 | // void onFailure();
13 | // void onCanceled();
14 | // void onPaused();
15 | // void onProgress(int progress);
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/MessageTask.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice;
2 |
3 | import android.os.AsyncTask;
4 |
5 | import com.lfork.a98620.lfree.imservice.message.Message;
6 |
7 | ///**
8 | // * Created by 98620 on 2017/8/18.
9 | // */
10 |
11 | class MessageTask extends AsyncTask {
12 |
13 | private static final String TAG = "DownloadTask";
14 | private long downloadedLength = 0;
15 | private static final int TYPE_SUCCESS = 0;
16 | private static final int TYPE_FAILED = 1;
17 | private static final int TYPE_PAUSED = 2;
18 | private static final int TYPE_CANCELED = 3;
19 | private static final int TYPE_DOWNLOADING = 4;
20 | private int DownloadStatus = TYPE_DOWNLOADING;
21 |
22 | private MessageListener listener;
23 | private boolean isCanceled = false;
24 | private boolean isPaused = false;
25 | private int lastProgress;
26 | private String address ;
27 |
28 |
29 | //传入参数为下载监听器, 随时监听下载任务的状态, 结合 publishProgress 和 onProgressUpdate 进行 UI刷新
30 | MessageTask(MessageListener listener, String address) {
31 | this.listener = listener;
32 | this.address = address;
33 | }
34 |
35 | @Override
36 | protected Integer doInBackground(String... strings) {
37 | return 0;
38 | }
39 |
40 | //在这里进行UI更新的调用。 配合listener 对下载过程中的状态进行监控 paused
41 | @Override
42 | protected void onProgressUpdate(Message... values) {
43 | super.onProgressUpdate(values);
44 | Message msg = values[0];
45 | if (msg != null) {
46 | listener.onReceived(msg);
47 | }
48 | }
49 |
50 |
51 | //下载任务完毕后(Success Failure Canceled) 就执行这个方法 。 配合listener对下载完毕的状态进行监控
52 | @Override
53 | protected void onPostExecute(Integer status) {
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/UDPMessageMaid.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice;
2 |
3 | import android.util.Log;
4 |
5 | import com.lfork.a98620.lfree.data.imdata.remote.MessageRemoteDataSource;
6 | import com.lfork.a98620.lfree.imservice.message.Message;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * 需要将服务器发来的消息进行分发。 分发给Repository
12 | */
13 | public class UDPMessageMaid extends Thread {
14 |
15 | private static final String TAG = "UDPMessageMaid";
16 |
17 | private boolean running;
18 |
19 | private MessageRemoteDataSource dataSource;
20 |
21 | private List messageReceiveQueue; //待处理的消息
22 |
23 | public UDPMessageMaid(MessageRemoteDataSource dataSource, List messageReceiveQueue) {
24 | this.dataSource = dataSource;
25 | this.messageReceiveQueue = messageReceiveQueue;
26 | }
27 |
28 | @Override
29 | public void run() {
30 | Message message = null;
31 | setRunning(true);
32 | while (isRunning()) {
33 | Log.d(TAG, "run: UDPMaid运行中");
34 | while (message == null) {
35 | if (messageReceiveQueue.size() > 0 && dataSource.getListener() != null) {
36 | message = messageReceiveQueue.remove(0);
37 | } else {
38 | try {
39 | sleep(100); //适当休眠,降低cpu负载
40 | } catch (InterruptedException e) {
41 | e.printStackTrace();
42 | }
43 | }
44 | }
45 | //处理信息:储存 + 发送
46 | dealMessage(message);
47 | message = null;
48 | }
49 |
50 | Log.d(TAG, "run: UDPMaid任务结束");
51 | }
52 |
53 | /**
54 | * 把接收到的消息进行分类储存 ,信息记录(聊天记录). 信息记录 。然后再把这条消息发给接收者。
55 | * 先这样,先不管储存的事情,而是先把消息推送到前台
56 | *
57 | * @param message
58 | */
59 | private void dealMessage(Message message) {
60 | dataSource.pushMessage(message);
61 | }
62 |
63 | /**
64 | * 如果客户端下线了, 那么就需要释放客户端在服务器所对应的处理线程
65 | */
66 | public void close() {
67 | //这里需要将 clientID 和 messageQueue里面的内容进行保存
68 | setRunning(false);
69 | }
70 |
71 |
72 | public boolean isRunning() {
73 | return running;
74 | }
75 |
76 | private void setRunning(boolean running) {
77 | this.running = running;
78 | }
79 |
80 | public void addMessage(Message message) {
81 | messageReceiveQueue.add(message);
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/message/Message.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice.message;
2 |
3 |
4 | import com.lfork.a98620.lfree.util.JSONUtil;
5 |
6 | import org.litepal.annotation.Column;
7 | import org.litepal.crud.DataSupport;
8 |
9 | public class Message extends DataSupport{
10 |
11 | private int senderID; //System的ID 为 0 , 如果是group(messageType为Group)的话, 这里的SenderID就是groupID
12 |
13 | private int receiverID;
14 |
15 | /**
16 | * messageId 实际上是message生成的时间 System.currentTimeMillis()
17 | */
18 | @Column(unique = true, defaultValue = "unknown")
19 | private long messageID;
20 |
21 | private String content;
22 |
23 | private MessageStatus status;
24 |
25 | private MessageContentType contentType;
26 |
27 | private MessageType type;
28 |
29 | private int chatType;
30 | public final static int SendType = 0, ReceiveType = 1;
31 |
32 | public Message(String content, int chatType){
33 | this.content = content;
34 | this.chatType = chatType;
35 | }
36 |
37 | public Message() {
38 | }
39 |
40 |
41 | public int getChatType(){
42 | return chatType;
43 | }
44 |
45 | public void setChatType(int chatType) {
46 | this.chatType = chatType;
47 | }
48 |
49 | public MessageType getType() {
50 | return type;
51 | }
52 |
53 | public void setType(MessageType type) {
54 | this.type = type;
55 | }
56 |
57 | public int getSenderID() {
58 | return senderID;
59 | }
60 |
61 | public void setSenderID(int senderID) {
62 | this.senderID = senderID;
63 | }
64 |
65 | public int getReceiverID() {
66 | return receiverID;
67 | }
68 |
69 | public void setReceiverID(int receiverID) {
70 | this.receiverID = receiverID;
71 | }
72 |
73 | public long getMessageID() {
74 | return messageID;
75 | }
76 |
77 | public void setMessageID(long messageID) {
78 | this.messageID = messageID;
79 | }
80 |
81 | public String getContent() {
82 | return content;
83 | }
84 |
85 | public void setContent(String content) {
86 | this.content = content;
87 | }
88 |
89 | public MessageContentType getContentType() {
90 | return contentType;
91 | }
92 |
93 | public void setContentType(MessageContentType contentType) {
94 | this.contentType = contentType;
95 | }
96 |
97 | public MessageStatus getStatus() {
98 | return status;
99 | }
100 |
101 | public void setStatus(MessageStatus status) {
102 | this.status = status;
103 | }
104 |
105 | @Override
106 | public String toString() {
107 | return JSONUtil.toJson(this);
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/message/MessageContentType.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice.message;
2 |
3 | public enum MessageContentType{
4 | COMMUNICATION_USER , //用户的聊天信息(单纯的字符串)
5 |
6 | COMMUNICATION_GROUP, //群组的聊天信息(单纯的字符串)
7 |
8 | COMMAND, //系统命令(可见或者不可见)
9 |
10 | NOTIFICATION //系统通知_好友添加的请求
11 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/message/MessageHelper.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice.message;
2 |
3 | import com.google.gson.reflect.TypeToken;
4 | import com.lfork.a98620.lfree.util.JSONUtil;
5 |
6 | import java.io.UnsupportedEncodingException;
7 | import java.net.DatagramPacket;
8 |
9 | public class MessageHelper {
10 | // public static UDPConnectionInfo UDPConnectionInfoParse(DatagramPacket dgp) {
11 | // InetAddress address = dgp.getAddress();
12 | // int port = dgp.getPort();
13 | // return new UDPConnectionInfo(address, port);
14 | // }
15 |
16 | public static Message messageParse(DatagramPacket dgp) {
17 | // Message message = null;
18 | //
19 | // byte[] bs = new byte[1000];
20 | //
21 | // DataInputStream dis = new DataInputStream(new ByteArrayInputStream(dgp.getData(), 0, dgp.getLength()));
22 | //
23 | // String msg = null;
24 | // try {
25 | // while (dis.available() > 0) {
26 | // // reads characters encoded with modified UTF-8
27 | // int index = dis.read(bs);
28 | // msg = Arrays.toString(bs);
29 | // // print
30 | // print( msg + " ");
31 | // }
32 | //
33 | // } catch (IOException e) {
34 | // e.printStackTrace();
35 | // }
36 | //
37 | //
38 | // //不对这里还需要将 字符串的message解析为Message对象才行
39 | // // String str = new String(dgp.getData(), 0, dgp.getLength(), "utf-8");
40 | // print("UDPConnection.startReceiveListener(): 接收到的信息:" + msg);
41 | // message = JSONUtil.parseJson(msg, new TypeToken() {
42 | // });
43 | //
44 | // //不对这里还需要将 字符串的message解析为Message对象才行
45 | // return message;
46 | ////
47 | Message message = null;
48 | try {
49 | String str = new String(dgp.getData(), 0, dgp.getLength(), "utf-8");
50 | // print("UDPConnection.startReceiveListener(): 接收到的信息:" + str );
51 | message = JSONUtil.parseJson(str, new TypeToken(){});
52 | } catch (UnsupportedEncodingException e) {
53 | e.printStackTrace();
54 | }
55 |
56 | //不对这里还需要将 字符串的message解析为Message对象才行
57 | return message;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/message/MessageStatus.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice.message;
2 |
3 | public enum MessageStatus{
4 | SENT,
5 |
6 | SENT_FAILED,
7 |
8 | SENDING,
9 |
10 | RECEIVED;
11 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/message/MessageType.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice.message;
2 |
3 | public enum MessageType {
4 | FEEDBACK,
5 | CONNECTION_INFO,
6 | NORMAL_MESSAGE
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/request/LoginListener.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice.request;
2 |
3 | import com.lfork.a98620.lfree.data.base.entity.User;
4 |
5 | public interface LoginListener {
6 | void succeed(User user);
7 | // void passwordError();
8 | //
9 | // void noSuchUser();
10 | //
11 | // void connectError();
12 | void failed(String log);
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/request/RegisterListener.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice.request;
2 |
3 | public interface RegisterListener {
4 | void succeed();
5 |
6 | void failed(String log);
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/request/Result.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice.request;
2 |
3 | public class Result {
4 |
5 | private int code;
6 |
7 | private String message;
8 |
9 | private T data;
10 |
11 | public int getCode() {
12 | return code;
13 | }
14 |
15 | public void setCode(int code) {
16 | this.code = code;
17 | }
18 |
19 | public String getMessage() {
20 | return message;
21 | }
22 |
23 | public void setMessage(String message) {
24 | this.message = message;
25 | }
26 |
27 | public T getData() {
28 | return data;
29 | }
30 |
31 | public void setData(T data) {
32 | this.data = data;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/imservice/request/UserRequestType.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.imservice.request;
2 |
3 | /**
4 | * 这个文件在客户端和服务器需要保持一致
5 | */
6 | public enum UserRequestType {
7 |
8 | DO_LOGIN(0),
9 |
10 | DO_REGISTER(1),
11 |
12 | DO_LOGOUT(15),
13 |
14 | GET_USER_INFO(2),
15 |
16 | UPDATE_USER_INFO(3),
17 |
18 | ADD_FRIEND(4),
19 |
20 | DELETE_FRIEND(5),
21 |
22 | GET_FRIEND_INFO(6),
23 |
24 | UPDATE_FRIEND_INFO(7),
25 |
26 | ADD_GROUP(8),
27 |
28 | DELETE_GROUP(9),
29 |
30 | UPDATE_GROUP(10),
31 |
32 | STRAT_MESSAGE_LISTENER(11),
33 |
34 | GET_FRIEND_LIST(12),
35 |
36 | GET_USERS(13),
37 |
38 | ALIVE_TEST(14);
39 |
40 | private int value;
41 |
42 | UserRequestType(int i) {
43 | this.value = i;
44 | }
45 |
46 | public void setValue(int value) {
47 | this.value = value;
48 | }
49 |
50 | public int getValue() {
51 | return value;
52 | }
53 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/login/LoginNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.login;
2 |
3 | import com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator;
4 |
5 | /**
6 | *
7 | * @author 98620
8 | * @date 2018/7/11
9 | */
10 | public interface LoginNavigator extends ViewModelNavigator {
11 | void loginSucceed();
12 |
13 | void loginFailed(String log);
14 |
15 | void openRegisterAct();
16 |
17 | void openForgetPasswordAct();
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/chatlist/ChatListFragmentViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.chatlist;
2 |
3 | import android.content.Context;
4 | import android.databinding.ObservableArrayList;
5 | import android.databinding.ObservableBoolean;
6 |
7 | import com.lfork.a98620.lfree.base.BaseViewModel;
8 | import com.lfork.a98620.lfree.base.FreeApplication;
9 | import com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator;
10 | import com.lfork.a98620.lfree.data.DataSource;
11 | import com.lfork.a98620.lfree.data.base.entity.User;
12 | import com.lfork.a98620.lfree.data.imdata.IMDataRepository;
13 |
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | /**
18 | * Created by 98620 on 2018/3/31.
19 | */
20 |
21 | public class ChatListFragmentViewModel extends BaseViewModel {
22 |
23 | public final ObservableArrayList mItems = new ObservableArrayList<>();
24 |
25 | public final ObservableBoolean dataIsLoading = new ObservableBoolean(true);
26 |
27 | public final ObservableBoolean dataIsEmpty = new ObservableBoolean(true);
28 |
29 | private IMDataRepository repository;
30 |
31 | private ViewModelNavigator navigator;
32 |
33 | ChatListFragmentViewModel(Context context) {
34 | super(context);
35 | }
36 |
37 | private void getChatList() {
38 | FreeApplication.executeThreadInDefaultThreadPool(() -> {
39 | repository = IMDataRepository.Companion.getInstance();
40 | repository.getChatUserList(new DataSource.GeneralCallback>() {
41 | @Override
42 | public void succeed(List data) {
43 | //这里要在ui线程里面执行数据的更新操作
44 | ArrayList items = new ArrayList<>();
45 | for (User u : data) {
46 | ChatListItemViewModel item = new ChatListItemViewModel(getContext(), u);
47 | items.add(item);
48 | dataIsEmpty.set(false);
49 | }
50 | mItems.clear();
51 | mItems.addAll(items);
52 | dataIsLoading.set(false);
53 |
54 | }
55 |
56 | @Override
57 | public void failed(String log) {
58 | showToast(log);
59 | }
60 | });
61 | });
62 | }
63 |
64 | @Override
65 | public void start() {
66 | getChatList();
67 | }
68 |
69 | @Override
70 | public void onDestroy() {
71 | super.onDestroy();
72 | navigator = null;
73 | }
74 |
75 | public void setNavigator(ChatListItemNavigator navigator) {
76 | super.setNavigator(navigator);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/chatlist/ChatListItemNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.chatlist;
2 |
3 | import com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator;
4 |
5 | /**
6 | * Created by 98620 on 2018/4/22.
7 | */
8 | public interface ChatListItemNavigator extends com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator {
9 |
10 | void openChatWindow(int userId, String userName);
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/chatlist/ChatListItemViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.chatlist;
2 |
3 | import android.content.Context;
4 | import android.databinding.ObservableField;
5 |
6 | import com.lfork.a98620.lfree.base.BaseViewModel;
7 | import com.lfork.a98620.lfree.data.base.entity.User;
8 | import com.lfork.a98620.lfree.base.Config;
9 |
10 | import java.lang.ref.WeakReference;
11 |
12 | /**
13 | * Created by 98620 on 2018/4/9.
14 | */
15 |
16 | public class ChatListItemViewModel extends BaseViewModel {
17 |
18 | public final ObservableField username = new ObservableField<>();
19 |
20 | public final ObservableField newMessage = new ObservableField<>();
21 |
22 | public final ObservableField newMessageTime = new ObservableField<>("没有消息");
23 |
24 | public final ObservableField imageUrl = new ObservableField<>();
25 |
26 | private int userId;
27 |
28 | public WeakReference reference;
29 |
30 | ChatListItemViewModel(Context context, User user) {
31 | super(context);
32 |
33 | username.set(user.getUserName());
34 | imageUrl.set(Config.ServerURL + "/image" + user.getUserImagePath());
35 | userId = user.getUserId();
36 | }
37 |
38 | public void onClick() {
39 | if (reference != null && reference.get() != null) {
40 | reference.get().openChatWindow(userId, username.get());
41 | }
42 | }
43 |
44 |
45 | @Override
46 | public void setNavigator(Object navigator) {
47 | super.setNavigator(navigator);
48 | reference = new WeakReference<>((ChatListItemNavigator) navigator);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/community/CommunityArticle.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.community;
2 |
3 | import com.lfork.a98620.lfree.base.BaseViewModel;
4 |
5 | import java.util.List;
6 |
7 | public class CommunityArticle extends BaseViewModel {
8 | private String article;
9 | private int articleId;
10 | private int publisherId; //发布人id
11 | private String articleTime;
12 | private List imageUriList;
13 | private String headImgUri;
14 | private String headName;
15 |
16 | public String getHeadImgUri() {
17 | return headImgUri;
18 | }
19 |
20 | public void setHeadImgUri(String headImgUri) {
21 | this.headImgUri = headImgUri;
22 | }
23 |
24 | public String getHeadName() {
25 | return headName;
26 | }
27 |
28 | public void setHeadName(String headName) {
29 | this.headName = headName;
30 | }
31 |
32 | public String getArticle() {
33 | return article;
34 | }
35 |
36 | public void setArticle(String article) {
37 | this.article = article;
38 | }
39 |
40 | public int getArticleId() {
41 | return articleId;
42 | }
43 |
44 | public void setArticleId(int articleId) {
45 | this.articleId = articleId;
46 | }
47 |
48 | public int getPublisherId() {
49 | return publisherId;
50 | }
51 |
52 | public void setPublisherId(int publisherId) {
53 | this.publisherId = publisherId;
54 | }
55 |
56 | public String getArticleTime() {
57 | return articleTime;
58 | }
59 |
60 | public void setArticleTime(String articleTime) {
61 | this.articleTime = articleTime;
62 | }
63 |
64 | public List getImageUriList() {
65 | return imageUriList;
66 | }
67 |
68 | public void setImageUriList(List imageUriList) {
69 | this.imageUriList = imageUriList;
70 | }
71 |
72 | public String getUrl() {
73 | return "http://imyth.top:8080/community_server/getcommunitycomment?articleId=" + articleId;
74 | }
75 |
76 | @Override
77 | public void start() {
78 |
79 | }
80 |
81 | @Override
82 | public void onDestroy() {
83 | super.onDestroy();
84 | }
85 | }
86 |
87 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/community/CommunityArticleAdapter.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.community;
2 |
3 | import android.databinding.DataBindingUtil;
4 | import android.databinding.ViewDataBinding;
5 | import android.support.annotation.NonNull;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.view.LayoutInflater;
8 | import android.view.ViewGroup;
9 |
10 | import com.lfork.a98620.lfree.BR;
11 | import com.lfork.a98620.lfree.R;
12 |
13 | import java.util.List;
14 |
15 | public class CommunityArticleAdapter extends RecyclerView.Adapter {
16 |
17 | private List itemViewModelList;
18 |
19 | public CommunityArticleAdapter(List itemViewModelList) {
20 | this.itemViewModelList = itemViewModelList;
21 | }
22 |
23 | @NonNull
24 | @Override
25 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
26 | return ViewHolder.create(LayoutInflater.from(parent.getContext()), parent, viewType);
27 | }
28 |
29 | @Override
30 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
31 | holder.bindTo(itemViewModelList.get(position));
32 | }
33 |
34 | @Override
35 | public int getItemCount() {
36 | return itemViewModelList.size();
37 | }
38 |
39 | static class ViewHolder extends RecyclerView.ViewHolder {
40 |
41 | ViewDataBinding binding;
42 |
43 | public ViewHolder(ViewDataBinding binding) {
44 | super(binding.getRoot());
45 | this.binding = binding;
46 | }
47 |
48 | static ViewHolder create(LayoutInflater inflater, ViewGroup parent, int type) {
49 | ViewDataBinding binding = DataBindingUtil.inflate(inflater, R.layout.main_community_frag_recycler_view_item, parent, false);
50 | return new ViewHolder(binding);
51 | }
52 |
53 | public void bindTo(CommunityArticle itemViewModel) {
54 | binding.setVariable(BR.viewModel, itemViewModel);
55 | binding.executePendingBindings();
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/community/CommunityBindingAdapter.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.community;
2 |
3 | import android.content.Intent;
4 | import android.databinding.BindingAdapter;
5 | import android.view.View;
6 |
7 | import com.lfork.a98620.lfree.articlecontent.ArticleContentActivity;
8 | import com.lfork.a98620.lfree.userinfo.UserInfoActivity;
9 | import com.lfork.a98620.lfree.util.ShareUtil;
10 |
11 | public class CommunityBindingAdapter {
12 |
13 | @BindingAdapter("android:toUserInfoActivity")
14 | public static void toUserInfoActivity(View view, int userId) {
15 | view.setOnClickListener((view1) -> {
16 | Intent intent = new Intent(view1.getContext(), UserInfoActivity.class);
17 | intent.putExtra("user_id", userId);
18 | view1.getContext().startActivity(intent);
19 | });
20 | }
21 |
22 | @BindingAdapter("android:toArticleContentActivity")
23 | public static void toArticleContentActivity(View view, int articleId) {
24 | view.setOnClickListener((view1) -> {
25 | Intent intent = new Intent(view1.getContext(), ArticleContentActivity.class);
26 | intent.putExtra("articleId", articleId);
27 | intent.putExtra("fromCommentButton", false);
28 | view1.getContext().startActivity(intent);
29 | });
30 | }
31 |
32 | @BindingAdapter("android:shareTo")
33 | public static void shareTo(View view, String url) {
34 | view.setOnClickListener((view1) -> {
35 | ShareUtil.shareTextBySystem(view.getContext(), url, "分享到");
36 | });
37 | }
38 |
39 | @BindingAdapter("android:toArticleComment")
40 | public static void toArticleComment(View view, int articleId) {
41 | view.setOnClickListener((view1) -> {
42 | Intent intent = new Intent(view.getContext(), ArticleContentActivity.class);
43 | intent.putExtra("articleId", articleId);
44 | intent.putExtra("fromCommentButton", true);
45 | view1.getContext().startActivity(intent);
46 | });
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/community/CommunityCallback.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.community;
2 |
3 | public interface CommunityCallback {
4 | void callback(Object data, int type);
5 | }
6 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/community/CommunityFragmentViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.community;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import com.lfork.a98620.lfree.base.BaseViewModel;
7 | import com.lfork.a98620.lfree.data.DataSource;
8 | import com.lfork.a98620.lfree.data.community.remote.CommunityRemoteDataSource;
9 |
10 | import static com.yalantis.ucrop.UCropFragment.TAG;
11 |
12 | public class CommunityFragmentViewModel extends BaseViewModel {
13 |
14 | @Override
15 | public void start() {
16 |
17 | }
18 |
19 | @Override
20 | public void onDestroy() {
21 | super.onDestroy();
22 | }
23 |
24 | CommunityFragmentViewModel(Context context) {
25 | super(context);
26 | }
27 |
28 | public void loadData(String fromTime, CommunityCallback callback) {
29 | Log.d(TAG, "loadData: 我要加载数据了");
30 | new Thread(() -> {
31 | CommunityRemoteDataSource.getINSTANCE().getArticleList(fromTime, new DataSource.GeneralCallback() {
32 | @Override
33 | public void succeed(Object data) {
34 | Log.d(TAG, "succeed: 我加载成功了,马上回调了");
35 | callback.callback(data, 1);
36 | }
37 |
38 | @Override
39 | public void failed(String log) {
40 | Log.d(TAG, "failed: " + log);
41 | Log.d(TAG, "failed: 我加载失败了,还是回调吧");
42 | callback.callback(0, 2);
43 | }
44 | });
45 | }).start();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/index/GoodsItemNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.index;
2 |
3 | /**
4 | * Created by 98620 on 2018/6/4.
5 | */
6 | interface GoodsItemNavigator {
7 |
8 | void openGoodsDetail(int goodsId, int categoryId);
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/index/GoodsItemViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.index;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.Nullable;
5 |
6 | import com.lfork.a98620.lfree.base.viewmodel.GoodsViewModel;
7 | import com.lfork.a98620.lfree.data.base.entity.Goods;
8 |
9 | import java.lang.ref.WeakReference;
10 |
11 | /**
12 | *
13 | * Created by 98620 on 2018/3/31.
14 | */
15 |
16 | public class GoodsItemViewModel extends GoodsViewModel{
17 |
18 | // This navigator is s wrapped in a WeakReference to avoid leaks because it has references to an
19 | // activity. There's no straightforward way to clear it for each item in a list adapter.
20 |
21 | @Nullable
22 | private WeakReference mNavigator;
23 |
24 | private GoodsItemViewModel(Context context, Goods g, int categoryId) {
25 | super(context, g, categoryId);
26 | }
27 |
28 | GoodsItemViewModel(Context context, Goods g) {
29 | this(context, g, 0);
30 | }
31 |
32 |
33 | public void onClick(){
34 | int goodsId = getId();
35 | if (goodsId == 0) {
36 | // Click happened before goods was loaded, no-op.
37 | return;
38 | }
39 | if (mNavigator != null && mNavigator.get() != null) {
40 | mNavigator.get().openGoodsDetail(goodsId, getCategoryId());
41 | }
42 | }
43 |
44 | public void setNavigator(GoodsItemNavigator mNavigator) {
45 | this.mNavigator = new WeakReference<>(mNavigator);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/index/GoodsRecyclerViewItemAdapter.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.index;
2 |
3 | import android.databinding.DataBindingUtil;
4 | import android.support.annotation.NonNull;
5 | import android.view.LayoutInflater;
6 | import android.view.ViewGroup;
7 |
8 | import com.lfork.a98620.lfree.base.adapter.RecyclerViewItemAdapter;
9 | import com.lfork.a98620.lfree.databinding.CommonGoodsRecycleItemBinding;
10 |
11 | /**
12 | *
13 | * Created by 98620 on 2018/3/31.
14 | */
15 |
16 | class GoodsRecyclerViewItemAdapter extends RecyclerViewItemAdapter {
17 |
18 | private GoodsItemNavigator mGoodsItemNavigator;
19 |
20 | private PagerDataRefreshListener listener;
21 |
22 |
23 | GoodsRecyclerViewItemAdapter(GoodsItemNavigator mGoodsItemNavigator,int layoutId) {
24 | super(layoutId);
25 | this.mGoodsItemNavigator = mGoodsItemNavigator;
26 | }
27 |
28 | @NonNull
29 | @Override
30 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
31 | CommonGoodsRecycleItemBinding binding = DataBindingUtil.inflate(LayoutInflater
32 | .from(parent.getContext()), getLayoutId(), parent, false);
33 |
34 | ViewHolder holder = new ViewHolder(binding.getRoot());
35 | holder.setBinding(binding);
36 | return holder;
37 |
38 | }
39 |
40 | @Override
41 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
42 | super.onBindViewHolder(holder, position);
43 | GoodsItemViewModel viewModel = (GoodsItemViewModel)getItems().get(position);
44 | viewModel.setNavigator(mGoodsItemNavigator);
45 |
46 | if (position + 1 == getItemCount()) {
47 | listener.startRefreshing();
48 | }
49 | if (position > 10) {
50 | listener.onDown();
51 | }
52 | }
53 |
54 | //滑动到最后
55 |
56 | public PagerDataRefreshListener getListener() {
57 | return listener;
58 | }
59 |
60 | public void setListener(PagerDataRefreshListener listener) {
61 | this.listener = listener;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/index/IndexFragmentNavigator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016, The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.lfork.a98620.lfree.main.index;
18 |
19 | /**
20 | * Defines the navigation actions that can be called from the Details screen.
21 | * 现在先不忙优化,先把im写完先
22 | */
23 | public interface IndexFragmentNavigator {
24 |
25 | void openSearchActivity();
26 |
27 | void openWebClient(String url);
28 | //ppt文档心得体会 源码
29 | // 数据库 配置文件
30 | // 需求文档
31 | // 概要设计
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/index/PagerDataRefreshListener.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.index;
2 |
3 | /**
4 | * Created by 98620 on 2018/5/5.
5 | */
6 | public interface PagerDataRefreshListener {
7 | void startRefreshing();
8 |
9 | void endRefresh();
10 |
11 | /**
12 | * 数据滑动到最下面了
13 | */
14 | void onDown();
15 |
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/index/PagerItemViewNavigator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016, The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.lfork.a98620.lfree.main.index;
18 |
19 | import com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator;
20 |
21 | /**
22 | * Defines the navigation actions that can be called from the Details screen.
23 | */
24 | public interface PagerItemViewNavigator extends ViewModelNavigator {
25 | void refreshEnd();
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/index/PagersDataBinding.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.index;
2 |
3 | import android.databinding.BindingAdapter;
4 | import android.support.v4.view.ViewPager;
5 |
6 | import com.lfork.a98620.lfree.data.base.entity.Category;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * Created by 98620 on 2018/6/2.
12 | */
13 | public class PagersDataBinding {
14 | @SuppressWarnings("unchecked")
15 | @BindingAdapter("tabs")
16 | public static void setTabs(ViewPager viewPager, List items) {
17 | // MyViewPagerAdapter adapter = (MyViewPagerAdapter) viewPager.getAdapter();
18 | PagerItemAdapter adapter = (PagerItemAdapter) viewPager.getAdapter();
19 | if (adapter != null)
20 | {
21 | adapter.replaceData(items, viewPager);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/myinfo/MyInfoFragmentNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.myinfo;
2 |
3 | import com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator;
4 |
5 | /**
6 | * Created by 98620 on 2018/6/23.
7 | */
8 | public interface MyInfoFragmentNavigator extends ViewModelNavigator {
9 | void openMyGoods();
10 |
11 | void openSettings();
12 |
13 | void openUserInfoDetail();
14 |
15 | void logoff();
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/myinfo/MyInfoFragmentViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.myinfo;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.lfork.a98620.lfree.base.viewmodel.UserViewModel;
6 | import com.lfork.a98620.lfree.data.DataSource;
7 | import com.lfork.a98620.lfree.data.base.entity.User;
8 | import com.lfork.a98620.lfree.data.user.UserDataRepository;
9 | import com.lfork.a98620.lfree.main.MainActivity;
10 | import com.lfork.a98620.lfree.base.Config;
11 |
12 | /**
13 | * Created by 98620 on 2018/4/5.
14 | */
15 |
16 | public class MyInfoFragmentViewModel extends UserViewModel {
17 |
18 | private MyInfoFragmentNavigator navigator;
19 |
20 | MyInfoFragmentViewModel(MainActivity context) {
21 | super(context);
22 | }
23 |
24 | private void getUserInfo() {
25 | UserDataRepository repository = UserDataRepository.INSTANCE;
26 | repository.getUserInfo(new DataSource.GeneralCallback() {
27 | @Override
28 | public void succeed(User data) {
29 | setUser(data);
30 | }
31 | @Override
32 | public void failed(String log) {
33 | showToast(log);
34 | }
35 | },repository.getUserId());
36 |
37 | }
38 |
39 | private void setUser(User user){
40 | username.set(user.getUserName());
41 | if (TextUtils.isEmpty(user.getUserDesc())) {
42 | description.set("该用户还没有自我介绍....");
43 | } else {
44 | description.set(user.getUserDesc());
45 | }
46 | imageUrl.set(Config.ServerURL + "/image" + user.getUserImagePath());
47 |
48 | }
49 |
50 | public void onQuit() {
51 | if (navigatorIsNotNull()) {
52 | navigator.logoff();
53 | }
54 |
55 | }
56 |
57 | public void openSettings() {
58 | if(navigatorIsNotNull()){
59 | navigator.openSettings();
60 | }
61 | }
62 |
63 | public void openUserInfoDetail() {
64 | if(navigatorIsNotNull()){
65 | navigator.openUserInfoDetail();
66 | }
67 |
68 | }
69 |
70 | public void openMyGoods() {
71 | if(navigatorIsNotNull()){
72 | navigator.openMyGoods();
73 | }
74 | }
75 |
76 | private boolean navigatorIsNotNull(){
77 | return navigator != null;
78 |
79 | }
80 |
81 | public void setNavigator(MyInfoFragmentNavigator navigator) {
82 | super.setNavigator(navigator);
83 | this.navigator = navigator;
84 | }
85 |
86 | @Override
87 | public void start() {
88 | getUserInfo();
89 | }
90 |
91 | @Override
92 | public void onDestroy() {
93 | super.onDestroy();
94 | navigator = null;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/main/publishinfo/PublishInfoFragment.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.main.publishinfo;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.annotation.NonNull;
6 | import android.support.v4.app.Fragment;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.Button;
11 |
12 | import com.lfork.a98620.lfree.R;
13 | import com.lfork.a98620.lfree.goodsuploadupdate.GoodsUploadUpdateActivity;
14 | import com.lfork.a98620.lfree.publisharticle.PublishArticleActivity;
15 |
16 | import java.util.Objects;
17 |
18 | public class PublishInfoFragment extends Fragment {
19 | private static final String TAG = "PublishInfoFragment";
20 |
21 | @Override
22 | public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
23 | Bundle savedInstanceState) {
24 | View view = inflater.inflate(R.layout.main_goods_upload_frag, container, false);
25 | Button upload = view.findViewById(R.id.btn_upload);
26 | upload.setOnClickListener(view1 -> {
27 | GoodsUploadUpdateActivity.openUploadActivityForResult(getActivity());
28 | });
29 |
30 | Button publishArticle = view.findViewById(R.id.btn_publish_article);
31 | publishArticle.setOnClickListener((view1) -> {
32 | Intent intent = new Intent(getContext(), PublishArticleActivity.class);
33 | Objects.requireNonNull(getActivity()).startActivityForResult(intent, 1);
34 | });
35 | // Inflate the layout for this fragment
36 | return view;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/mygoods/MyGoodsActivityNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.mygoods;
2 |
3 | import com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator;
4 |
5 | /**
6 | * Created by 98620 on 2018/5/5.
7 | */
8 | interface MyGoodsActivityNavigator extends ViewModelNavigator {
9 | void refreshFinished(String log);
10 |
11 | void loadMoreFinished(String log);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/mygoods/MyGoodsItemNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.mygoods;
2 |
3 | import com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator;
4 |
5 | public interface MyGoodsItemNavigator extends ViewModelNavigator {
6 | void openGoodsDetail(int goodsId, int categoryId);
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/mygoods/MyGoodsItemViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.mygoods;
2 |
3 | import android.content.Context;
4 |
5 | import com.lfork.a98620.lfree.base.viewmodel.GoodsViewModel;
6 | import com.lfork.a98620.lfree.data.base.entity.Goods;
7 |
8 | import java.lang.ref.WeakReference;
9 |
10 | /**
11 | * Created by 98620 on 2018/5/5.
12 | */
13 | public class MyGoodsItemViewModel extends GoodsViewModel{
14 |
15 |
16 |
17 | private WeakReference reference;
18 |
19 | MyGoodsItemViewModel(Context context, Goods g) {
20 | super(context, g);
21 |
22 | }
23 |
24 |
25 |
26 | @Override
27 | public void onClick(){
28 | if (reference != null && reference.get() != null)
29 | reference.get().openGoodsDetail(getId(), getCategoryId());
30 |
31 | }
32 |
33 | @Override
34 | public void setNavigator(Object navigator) {
35 | super.setNavigator(navigator);
36 | this.reference = new WeakReference<>((MyGoodsItemNavigator)navigator);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/register/RegisterNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.register;
2 |
3 | import com.lfork.a98620.lfree.data.base.entity.School;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * Created by 98620 on 2018/6/13.
9 | */
10 | public interface RegisterNavigator {
11 | void setupSpinner(List data);
12 |
13 | void success(String result);
14 |
15 | void failed(String result);
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/searchresult/GoodsSearchItemViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.searchresult;
2 |
3 | import android.content.Context;
4 |
5 | import com.lfork.a98620.lfree.base.viewmodel.GoodsViewModel;
6 | import com.lfork.a98620.lfree.data.base.entity.Goods;
7 |
8 | import java.lang.ref.WeakReference;
9 |
10 | /**
11 | * Created by 98620 on 2018/4/14.
12 | */
13 |
14 | public class GoodsSearchItemViewModel extends GoodsViewModel {
15 |
16 | private WeakReference reference;
17 |
18 | public GoodsSearchItemViewModel(Context context, Goods g) {
19 | super(context, g);
20 | }
21 |
22 | public void setNavigator(GoodsSearchNavigator navigator) {
23 | super.setNavigator(navigator);
24 | reference = new WeakReference<>(navigator);
25 | }
26 |
27 | public void onClick(){
28 | if (reference != null && reference.get() != null) {
29 | reference.get().openGoodsDetail(getId(), getCategoryId());
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/searchresult/GoodsSearchNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.searchresult;
2 |
3 | import com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator;
4 |
5 | /**
6 | * Created by 98620 on 2018/6/26.
7 | */
8 | public interface GoodsSearchNavigator extends ViewModelNavigator{
9 | void openGoodsDetail(int goodsId,int categoryId);
10 |
11 | void cancelSearch();
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/settings/SettingsActivity.kt:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.settings
2 |
3 | import android.os.Bundle
4 | import android.support.v7.app.ActionBar
5 | import android.support.v7.app.AppCompatActivity
6 | import android.view.Menu
7 | import android.view.MenuItem
8 | import com.lfork.a98620.lfree.R
9 | import java.util.*
10 |
11 | class SettingsActivity : AppCompatActivity() {
12 | override fun onCreate(savedInstanceState: Bundle?) {
13 | super.onCreate(savedInstanceState)
14 | setContentView(R.layout.settings_act)
15 | setupActionBar()
16 | }
17 |
18 | private fun setupActionBar() {
19 | val actionBar = supportActionBar
20 | Objects.requireNonNull(actionBar).setDisplayShowTitleEnabled(true)
21 | actionBar!!.title = "设置"
22 | // 决定左上角图标的右侧是否有向左的小箭头, true
23 | actionBar.setDisplayHomeAsUpEnabled(true)
24 | // 有小箭头,并且图标可以点击
25 | actionBar.setDisplayShowHomeEnabled(false)
26 | }
27 |
28 | override fun onCreateOptionsMenu(menu: Menu): Boolean {
29 | // getMenuInflater().inflate(R.menu.common_action_bar, menu);
30 | // MenuItem item = menu.getItem(0);
31 | // item.setTitle("编辑");
32 | return true
33 | }
34 |
35 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
36 | when (item.itemId) {
37 | android.R.id.home -> finish()
38 | // case R.id.menu1:
39 | // Intent intent = new Intent(UserInfoThisActivity.this, UserInfoEditActivity.class);
40 | // startActivityForResult(intent, 4);
41 | else -> {
42 | }
43 | }
44 | return super.onOptionsItemSelected(item)
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/userinfo/UserInfoViewModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.userinfo;
2 |
3 | import android.content.Context;
4 | import android.text.TextUtils;
5 |
6 | import com.lfork.a98620.lfree.base.viewmodel.UserViewModel;
7 | import com.lfork.a98620.lfree.base.viewmodel.ViewModelNavigator;
8 | import com.lfork.a98620.lfree.data.DataSource;
9 | import com.lfork.a98620.lfree.data.base.entity.User;
10 | import com.lfork.a98620.lfree.data.user.UserDataRepository;
11 | import com.lfork.a98620.lfree.base.Config;
12 |
13 | /**
14 | * Created by 98620 on 2018/4/13.
15 | */
16 |
17 | public class UserInfoViewModel extends UserViewModel {
18 |
19 |
20 | private ViewModelNavigator navigator;
21 |
22 | private int userId;
23 |
24 | UserInfoViewModel(Context context, int userId) {
25 | super(context);
26 | this.userId = userId;
27 | }
28 |
29 | @Override
30 | public void start() {
31 | getUserInfo();
32 | }
33 |
34 | private void getUserInfo() {
35 | UserDataRepository repository = UserDataRepository.INSTANCE;
36 | repository.getUserInfo(new DataSource.GeneralCallback() {
37 | @Override
38 | public void succeed(User user) {
39 | username.set(user.getUserName());
40 | if (TextUtils.isEmpty(user.getUserDesc())) {
41 | description.set("该用户还没有自我介绍....");
42 | } else {
43 | description.set(user.getUserDesc());
44 | }
45 | imageUrl.set(Config.ServerURL + "/image" + user.getUserImagePath());
46 | email.set(user.getUserEmail());
47 | phone.set(user.getUserPhone());
48 | studentNumber.set(user.getUserId() + "");
49 |
50 | if (user.getUserSchool() == null) {
51 | school.set("cuit");
52 | } else {
53 | school.set(user.getUserSchool().getSchoolName());
54 | }
55 |
56 |
57 | }
58 | @Override
59 | public void failed(String log) {
60 | if (navigator != null) {
61 | navigator.showToast(log);
62 | }
63 | }
64 | }, userId);
65 | }
66 |
67 |
68 | public int getUserId() {
69 | return userId;
70 | }
71 |
72 |
73 |
74 | @Override
75 | public void onDestroy() {
76 | super.onDestroy();
77 | navigator = null;
78 | }
79 |
80 | public void setNavigator(ViewModelNavigator navigator) {
81 | this.navigator = navigator;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/userinfoedit/UserInfoEditNavigator.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.userinfoedit;
2 |
3 | import com.lfork.a98620.lfree.data.base.entity.School;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * Created by 98620 on 2018/6/13.
9 | */
10 | public interface UserInfoEditNavigator {
11 | void setupSpinner(List data, int currentSchoolId);
12 |
13 | void success(String result);
14 |
15 | void failed(String result);
16 |
17 | void backToUserInfoAct(int result, String log);
18 |
19 | void showMessage(String msg);
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/JSONUtil.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.reflect.TypeToken;
5 |
6 | /** en?
7 | * Created by 98620 on 2018/2/1.
8 | */
9 |
10 | public class JSONUtil {
11 | /**
12 | *
13 | * @param jsonData 符合JSON语法规则的字符串
14 | * @param token 传递参数的时候这样写:new TypeToken() {}, 比如:parseJson(str1, new TypeToken>>(){})
15 | * 泛型会被擦除, 所以Token需要单独传参数
16 | * @return fromJson会自动根据JSONData的内容转化为POJO 或者是List
17 | */
18 | public static T parseJson(String jsonData, TypeToken> token) {
19 | try {
20 | return new Gson().fromJson(jsonData, token.getType());
21 | } catch (Exception e) {
22 | e.printStackTrace();
23 | return null;
24 | }
25 | }
26 |
27 | public static String toJson(T object){
28 | try {
29 | return new Gson().toJson(object);
30 | } catch (Exception e) {
31 | e.printStackTrace();
32 | return null;
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/LFreeGlideModel.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util;
2 |
3 | import com.bumptech.glide.annotation.GlideModule;
4 | import com.bumptech.glide.module.AppGlideModule;
5 |
6 | /**
7 | *
8 | * Created by 98620 on 2018/3/23.
9 | */
10 |
11 | @GlideModule
12 | public class LFreeGlideModel extends AppGlideModule {
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/Print.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util;
2 |
3 | import android.util.Log;
4 |
5 | public class Print {
6 | private static final String TAG = "Print";
7 | public static void print(String content){
8 | Log.d(TAG, "print: " + content);
9 | }
10 |
11 | public static void print(Object content){
12 | Log.d(TAG, "print: " + content);
13 | }
14 |
15 | public static void print(String Tag, String content){
16 | Log.d(Tag, "print: " + content);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/QMUI/QMUILangHelper.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util.QMUI;
2 |
3 | import android.support.annotation.Nullable;
4 |
5 | import java.io.Closeable;
6 | import java.io.IOException;
7 | import java.util.Locale;
8 |
9 | /**
10 | * @author cginechen
11 | * @date 2016-03-17
12 | */
13 | public class QMUILangHelper {
14 |
15 | /**
16 | * 获取数值的位数,例如9返回1,99返回2,999返回3
17 | *
18 | * @param number 要计算位数的数值,必须>0
19 | * @return 数值的位数,若传的参数小于等于0,则返回0
20 | */
21 | public static int getNumberDigits(int number) {
22 | if (number <= 0) return 0;
23 | return (int) (Math.log10(number) + 1);
24 | }
25 |
26 |
27 | public static int getNumberDigits(long number) {
28 | if (number <= 0) return 0;
29 | return (int) (Math.log10(number) + 1);
30 | }
31 |
32 | /**
33 | * 规范化价格字符串显示的工具类
34 | *
35 | * @param price 价格
36 | * @return 保留两位小数的价格字符串
37 | */
38 | public static String regularizePrice(float price) {
39 | return String.format(Locale.CHINESE, "%.2f", price);
40 | }
41 |
42 | /**
43 | * 规范化价格字符串显示的工具类
44 | *
45 | * @param price 价格
46 | * @return 保留两位小数的价格字符串
47 | */
48 | public static String regularizePrice(double price) {
49 | return String.format(Locale.CHINESE, "%.2f", price);
50 | }
51 |
52 |
53 | public static boolean isNullOrEmpty(@Nullable CharSequence string) {
54 | return string == null || string.length() == 0;
55 | }
56 |
57 | public static void close(Closeable c) {
58 | if (c != null) {
59 | try {
60 | c.close();
61 | } catch (IOException e) {
62 | e.printStackTrace();
63 | }
64 | }
65 | }
66 |
67 | public static boolean objectEquals(Object a, Object b) {
68 | return (a == b) || (a != null && a.equals(b));
69 | }
70 |
71 | public static int constrain(int amount, int low, int high) {
72 | return amount < low ? low : (amount > high ? high : amount);
73 | }
74 |
75 | public static float constrain(float amount, float low, float high) {
76 | return amount < low ? low : (amount > high ? high : amount);
77 | }
78 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/QMUI/QMUILog.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util.QMUI;
2 |
3 | /**
4 | *
5 | * @author cginechen
6 | * @date 2016-08-11
7 | */
8 | public class QMUILog {
9 | public interface QMUILogDelegate {
10 | void e(final String tag, final String msg, final Object ... obj);
11 | void w(final String tag, final String msg, final Object ... obj);
12 | void i(final String tag, final String msg, final Object ... obj);
13 | void d(final String tag, final String msg, final Object ... obj);
14 | void printErrStackTrace(String tag, Throwable tr, final String format, final Object ... obj);
15 | }
16 |
17 | private static QMUILogDelegate sDelegete = null;
18 |
19 | public static void setDelegete(QMUILogDelegate delegete) {
20 | sDelegete = delegete;
21 | }
22 |
23 | public static void e(final String tag, final String msg, final Object ... obj) {
24 | if (sDelegete != null) {
25 | sDelegete.e(tag, msg, obj);
26 | }
27 | }
28 |
29 | public static void w(final String tag, final String msg, final Object ... obj) {
30 | if (sDelegete != null) {
31 | sDelegete.w(tag, msg, obj);
32 | }
33 | }
34 |
35 | public static void i(final String tag, final String msg, final Object ... obj) {
36 | if (sDelegete != null) {
37 | sDelegete.i(tag, msg, obj);
38 | }
39 | }
40 |
41 | public static void d(final String tag, final String msg, final Object ... obj) {
42 | if (sDelegete != null) {
43 | sDelegete.d(tag, msg, obj);
44 | }
45 | }
46 |
47 | public static void printErrStackTrace(String tag, Throwable tr, final String format, final Object ... obj) {
48 | if (sDelegete != null) {
49 | sDelegete.printErrStackTrace(tag, tr, format, obj);
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/ShareUtil.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.text.TextUtils;
6 | import android.util.Log;
7 |
8 | /**
9 | * Created by 98620 on 2018/6/20.
10 | */
11 | public class ShareUtil {
12 | private static final String TAG = "ShareUtil";
13 | public static void shareTextBySystem(Context context, String text, String tips){
14 | if (context == null || TextUtils.isEmpty(text) || TextUtils.isEmpty(tips)) {
15 | Log.d(TAG, "shareTextBySystem: 参数不能为空");
16 | return;
17 | }
18 | Intent intent = new Intent();
19 | intent.setAction(Intent.ACTION_SEND)
20 | .setType("text/plain");
21 | intent.putExtra(Intent.EXTRA_TEXT, text);
22 | context.startActivity(Intent.createChooser(intent, tips));
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/SharedPrefUtil.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util;
2 |
3 | /**
4 | *
5 | * @author 98620
6 | * @date 2018/7/11
7 | */
8 | public class SharedPrefUtil {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/ThreadUtil.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util;
2 |
3 | /**
4 | * Created by 98620 on 2018/7/15.
5 | */
6 | public class ThreadUtil {
7 |
8 | void getFixedThreadPool(){
9 | // Executors.newFixedThreadPool();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/TimeUtil.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util;
2 |
3 | import android.text.format.DateFormat;
4 |
5 | import java.util.Date;
6 |
7 | /**
8 | * Created by 98620 on 2018/6/13.
9 | */
10 | public class TimeUtil {
11 | public static String getStandardTime(){
12 | return DateFormat.format("yyyy-MM-dd HH:mm:ss", new Date()).toString();
13 | }
14 |
15 | public static String getBiggestTime(){
16 | return DateFormat.format("9999-01-02 13:44:44", new Date()).toString();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/ToastUtil.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util;
2 |
3 | import android.content.Context;
4 | import android.os.Looper;
5 | import android.widget.Toast;
6 |
7 | /**
8 | * Created by 98620 on 2018/4/14.
9 | */
10 |
11 | public class ToastUtil {
12 | public static void showLong(Context context, String content){
13 | if (!Thread.currentThread().getName().equals("main")) {
14 | if (Looper.myLooper() == null)
15 | {
16 | Looper.prepare();
17 | }
18 | }
19 | Toast.makeText(context, content, Toast.LENGTH_LONG).show();
20 | }
21 |
22 | public static void showShort(Context context, String content){
23 | if (!Thread.currentThread().getName().equals("main")) { //不能在非主线程里面直接Toast Can't create handler inside thread that has not called Looper.prepare()
24 | if (Looper.myLooper() == null)
25 | {
26 | Looper.prepare();
27 | }
28 | }
29 | Toast.makeText(context, content, Toast.LENGTH_SHORT).show();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/UserValidation.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util;
2 | import android.text.TextUtils;
3 |
4 | import java.util.regex.Matcher;
5 | import java.util.regex.Pattern;
6 |
7 | public class UserValidation {
8 | /**
9 | * 所运用的正则表达式的集合:
10 | * userId 的正则表达式:"-?[1-9]\\d*" (数字)
11 | * userName的正则表达式:"[A-Za-z0-9_\\-\\u4e00-\\u9fa5]+" ()
12 | * userPassword 的正则表达式:"^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$" (只能位数字或者字母) //8位到16位
13 | * userEmail 的正则表达式:"\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}"
14 | * userPhone 的正则表达式:"0?(13|14|15|18)[0-9]{9}"
15 | *
16 | */
17 |
18 | private static final String regex_UserId = "[1-9]\\d{9}";
19 |
20 | private static final String regex_UserName = "[A-Za-z0-9_\\-\\u4e00-\\u9fa5]{5,16}";
21 |
22 | private static final String regex_UserPassword = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$";
23 |
24 | private static final String regex_UserEmail = "\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}";
25 |
26 | private static final String regex_UserPhone = "0?(13|14|15|18)[0-9]{9}";
27 |
28 | // 对注册时的数据进行验证
29 | public static String RegisterValidation(String userId, String userName, String userPassword, String passwordRepeat) {
30 |
31 | if (TextUtils.isEmpty(userId) || TextUtils.isEmpty(userName) || TextUtils.isEmpty(userPassword) || TextUtils.isEmpty(passwordRepeat)) {
32 | return "请输入完整的注册信息";
33 | }
34 |
35 | if (!RegexValidation(userId, regex_UserId)) {
36 | return "学号必须是10位";
37 | }
38 |
39 | if (!RegexValidation(userName, regex_UserName)) {
40 | return "用户名不符合规范";
41 | }
42 |
43 | if (!RegexValidation(userPassword, regex_UserPassword)) {
44 | return "密码不符合规范";
45 | }
46 |
47 |
48 | if (!userPassword.equals(passwordRepeat) ) {
49 | return "两次输入的密码必须相同";
50 | }
51 |
52 | return null;
53 | }
54 |
55 | // 对登录的数据进行验证
56 | public static boolean LoginValidation(String userId, String userPassword) {
57 | return RegexValidation(userId, regex_UserId) && RegexValidation(userPassword, regex_UserPassword);
58 | }
59 |
60 | // 对修改用户信息后保存操作之前的数据进行修改
61 | public static boolean SaveValidation(String userId, String userName, String userPassword, String userEmail,
62 | String userPhone) {
63 | return RegexValidation(userId, regex_UserId) && RegexValidation(userName, regex_UserName)
64 | && RegexValidation(userPassword, regex_UserPassword) && RegexValidation(userEmail, regex_UserEmail)
65 | && RegexValidation(userPhone, regex_UserPhone);
66 | }
67 |
68 | // 传入要验证的字段,以及需要的正则表达式, 进行字段的验证
69 | private static boolean RegexValidation(String args, String regex) {
70 | Pattern pattern = Pattern.compile(regex);
71 | Matcher matcher = pattern.matcher(args);
72 | System.out.println(matcher.matches());
73 | return matcher.matches();
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/Utils.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util;
2 |
3 | import android.content.Context;
4 |
5 | import com.lfork.a98620.lfree.base.FreeApplication;
6 |
7 | /**
8 | * Created by 98620 on 2018/7/11.
9 | */
10 | class Utils {
11 | public static Context getApp() {
12 | return FreeApplication.getContext();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/util/ui/MyItemDecoration.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.util.ui;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.view.View;
9 |
10 | public class MyItemDecoration extends RecyclerView.ItemDecoration{
11 | private int halfSpace;
12 | private Paint paint;
13 | /**
14 | * @param space item之间的间隙
15 | */
16 | public MyItemDecoration(int space, Context context, int color) {
17 | setSpace(space);
18 | paint = new Paint();
19 | paint.setAntiAlias(true);//抗锯齿
20 | paint.setColor(color);//设置背景色
21 | }
22 | public void setSpace(int space) {
23 | this.halfSpace = space / 2;
24 | }
25 | /**
26 | *
27 | * 重写onDraw 方法以实现recyclerview的item之间的间隙的背景
28 | * @param c 画布
29 | * @param parent 使用该 ItemDecoration 的 RecyclerView 对象实例
30 | * @param state 使用该 ItemDecoration 的 RecyclerView 对象实例的状态
31 | */
32 | @Override
33 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
34 | super.onDraw(c, parent, state);
35 | int outLeft, outTop, outRight, outBottom,viewLeft,viewTop,viewRight,viewBottom;
36 | int childCount = parent.getChildCount();
37 | for (int i = 0; i < childCount; i++) {
38 | View view = parent.getChildAt(i);
39 | viewLeft = view.getLeft();
40 | viewTop = view.getTop();
41 | viewRight = view.getRight();
42 | viewBottom = view.getBottom();
43 | // item外层的rect在RecyclerView中的坐标
44 | outLeft = viewLeft - halfSpace;
45 | outTop = viewTop - halfSpace;
46 | outRight = viewRight + halfSpace;
47 | outBottom = viewBottom + halfSpace;
48 | //item 上方的矩形
49 | c.drawRect(outLeft, outTop, outRight,viewTop, paint);
50 | //item 左边的矩形
51 | c.drawRect(outLeft,viewTop,viewLeft,viewBottom,paint);
52 | //item 右边的矩形
53 | c.drawRect(viewRight,viewTop,outRight,viewBottom,paint);
54 | //item 下方的矩形
55 | c.drawRect(outLeft,viewBottom,outRight,outBottom,paint);
56 | }
57 | }
58 | @Override
59 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
60 | outRect.top = halfSpace;
61 | outRect.bottom = halfSpace;
62 | outRect.left = halfSpace;
63 | outRect.right = halfSpace;
64 | }
65 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lfork/a98620/lfree/welcome/WelcomeActivity.java:
--------------------------------------------------------------------------------
1 | package com.lfork.a98620.lfree.welcome;
2 |
3 | import android.content.Intent;
4 | import android.os.Build;
5 | import android.os.Bundle;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.view.View;
8 | import android.widget.ImageView;
9 |
10 | import com.bumptech.glide.Glide;
11 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
12 | import com.lfork.a98620.lfree.R;
13 | import com.lfork.a98620.lfree.base.FreeApplication;
14 | import com.lfork.a98620.lfree.login.LoginActivity;
15 | import com.lfork.a98620.lfree.util.GlideOptions;
16 |
17 | public class WelcomeActivity extends AppCompatActivity {
18 |
19 | private static final String TAG = "WelcomeActivity";
20 | private WelcomeActivity welcomeActivity;
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.welcome_act);
26 | ImageView welcome = findViewById(R.id.welcome_image);
27 | GlideOptions options = GlideOptions.diskCacheStrategyOf(DiskCacheStrategy.NONE).skipMemoryCache(true);
28 | Glide.with(this).load(R.drawable.welcome_pic).apply(options).into(welcome);
29 | welcomeActivity = this;
30 | hideSystemNavigationBar();
31 |
32 | FreeApplication.getDefaultThreadPool().execute(() -> {
33 | try {
34 | Thread.sleep(2000);
35 | } catch (InterruptedException e) {
36 | e.printStackTrace();
37 | }
38 | runOnUiThread(() -> {
39 | Intent intent = new Intent(welcomeActivity, LoginActivity.class);
40 | welcomeActivity.startActivity(intent);
41 | welcomeActivity.finish();
42 | });
43 | });
44 |
45 |
46 | }
47 |
48 | private void hideSystemNavigationBar() {
49 | if (Build.VERSION.SDK_INT >= 19) {
50 | View decorView = getWindow().getDecorView();
51 | int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
52 | | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN;
53 | decorView.setSystemUiVisibility(uiOptions);
54 | }
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/chatwindow_mesage_left.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-hdpi/chatwindow_mesage_left.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/chatwindow_message_right.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-hdpi/chatwindow_message_right.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/goods_upload_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-hdpi/goods_upload_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/chatwindow_mesage_left.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-mdpi/chatwindow_mesage_left.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/chatwindow_message_right.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-mdpi/chatwindow_message_right.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/goods_upload_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-mdpi/goods_upload_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/user_detail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-v24/user_detail.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/user_email.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-v24/user_email.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/user_phone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-v24/user_phone.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/user_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-v24/user_user.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/chatwindow_mesage_left.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-xhdpi/chatwindow_mesage_left.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/chatwindow_message_right.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-xhdpi/chatwindow_message_right.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/goods_upload_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-xhdpi/goods_upload_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/chatwindow_mesage_left.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-xxhdpi/chatwindow_mesage_left.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/chatwindow_message_right.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-xxhdpi/chatwindow_message_right.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/goods_upload_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-xxhdpi/goods_upload_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/chatwindow_mesage_left.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-xxxhdpi/chatwindow_mesage_left.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/chatwindow_message_right.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable-xxxhdpi/chatwindow_message_right.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/back.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/background.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/chatwindow_mesage_left.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/chatwindow_mesage_left.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/chatwindow_message_right.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/chatwindow_message_right.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/close.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dark_gray.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/divider.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
19 |
20 |
21 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_arrow_upward_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_camera.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_comment_message.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_community_comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/ic_community_comment.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_community_in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/ic_community_in.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_community_like_in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/ic_community_like_in.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_community_like_side.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/ic_community_like_side.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_community_share_side.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/ic_community_share_side.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_community_side.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/ic_community_side.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_contacts_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_goods_details.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_goods_kinds.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_goods_location.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_goods_name.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_main_publish_new_community.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_main_publish_new_goods.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_mygoods_box.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/ic_mygoods_box.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_photo.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_school.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/ic_school.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_school_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_search_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_talk_notalk.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/item_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/login_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/login_logo.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/login_shape_user_rectangle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_community_btn_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_goods_btn_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_goods_in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/main_goods_in.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_goods_side.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/main_goods_side.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_ic_search_grey_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_ic_search_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/main_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_index_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/main_index_search.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_my_btn_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_my_in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/main_my_in.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_my_side.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/main_my_side.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_publish.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/main_publish.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_shape_search_rectangle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_talk_btn_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_talk_in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/main_talk_in.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_talk_side.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/main_talk_side.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/main_text_color_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/my_data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/my_data.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/my_mygoods.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/my_mygoods.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/my_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/my_settings.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/photo_select.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/photo_select.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/red.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/trash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/trash.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/trash2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/trash2.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/user_default_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/user_default_0.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/user_default_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/user_default_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/user_detail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/user_detail.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/user_email.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/user_email.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/user_no.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/user_no.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/user_phone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/user_phone.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/user_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/user_user.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/welcome_pic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/drawable/welcome_pic.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/white.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_publish_article.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
11 |
12 |
13 |
14 |
17 |
18 |
22 |
23 |
29 |
30 |
36 |
37 |
38 |
42 |
43 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/chat_window_msg_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
16 |
17 |
22 |
23 |
24 |
25 |
32 |
33 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/community_comment_include.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
15 |
16 |
21 |
22 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/goods_detail_seller_include.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
12 |
13 |
14 |
19 |
20 |
30 |
31 |
40 |
41 |
52 |
53 |
54 |
55 |
56 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/goods_search_include.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
18 |
19 |
28 |
29 |
40 |
49 |
50 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/image_browser_act.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_chat_list_frag.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
33 |
34 |
43 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_community_frag.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
19 |
20 |
24 |
25 |
35 |
36 |
37 |
46 |
47 |
53 |
54 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_goods_upload_frag.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
19 |
20 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/refresh_footer.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/web_client_act.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/welcome_act.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/common_action_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/goods_detail_action_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v27/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #0aa4ea
4 | #ffffff
5 | #000
6 | #b1bc39
7 | #f4f4f8
8 | #c1c4d6
9 | #abafae
10 | #fff
11 | #ffd648
12 | #d7d7d7
13 |
14 | #80000000
15 | #00000000
16 | #000
17 |
18 | #FF3B00
19 | #990000
20 | #4C535B
21 | #ff7e8a97
22 |
23 | #f2f2f2
24 |
25 | #0aa4ea
26 |
27 | #6cf
28 |
29 | #fafafa
30 |
31 | #f2f2f2
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 | 16dp
7 | 180dp
8 | 16dp
9 | 8dp
10 | 176dp
11 | 300dp
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/goods_categories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - 数码影音
5 | - 鞋服配饰
6 | - 家居日用
7 | - 手机通讯
8 | - 电脑办公
9 | - 图书影像
10 | - 其他
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | L.Free
3 |
4 | 用户名/学号/邮箱
5 | 用户名
6 | 用户名(5~16位)
7 | 学号 10位
8 | 密码
9 | 字母+数字,8~16位
10 | 注册
11 | 注册新用户
12 | Welcome to L.free!
13 |
14 | 登录
15 | Sign in
16 | This email address is invalid
17 | 密码太短
18 | 请检查你的账号和密码
19 | 请输入账号
20 | "Contacts permissions are needed for providing email
21 | completions."
22 |
23 | 忘记密码?
24 | Hello blank fragment
25 | login_user_icon
26 | login_password_icon
27 | 请再输入一遍密码
28 | 正在登录…
29 | 正在加载…
30 |
31 | Send
32 | Type something here
33 | TODO
34 | 搜索中…
35 | temp school : cuit
36 | 编辑
37 | 删除
38 | 分享
39 | 位置:
40 | 提交
41 | 正在上传…
42 | 选择图片上传
43 | 商品名
44 | 商品描述
45 | 原价:
46 | 卖价:
47 | 分类:
48 | 私聊
49 | 聊天记录
50 | 您还没有与卖家交流过,赶快去寻找卖家进行交流吧~~
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
11 |
12 |
13 |
17 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/file_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/bash.exe.stackdump:
--------------------------------------------------------------------------------
1 | Stack trace:
2 | Frame Function Args
3 | 000FFFF5E38 0018005D19E (0018024212D, 00180223C26, 000FFFF5E38, 000FFFF4D30)
4 | 000FFFF5E38 001800463F9 (00000000000, 00000000000, 00000000000, 001005F0D44)
5 | 000FFFF5E38 00180046432 (001802421E9, 000FFFF5CE8, 000FFFF5E38, 00000000000)
6 | 000FFFF5E38 001800A9EEF (00000000000, 00000000000, 00000000000, 00000000000)
7 | 000FFFF5E38 001800AA13D (000FFFF5E50, 00000000000, 00000000000, 00000000000)
8 | 000FFFF60C0 001800AB3A4 (000FFFF5E50, 00000000000, 00000000000, 00000000000)
9 | End of stack trace
10 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.2.60'
5 |
6 | repositories {
7 | google()
8 | jcenter()
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.0.1'
12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | google()
22 | jcenter()
23 | maven { url "https://jitpack.io" }
24 |
25 | }
26 | }
27 |
28 | task clean(type: Delete) {
29 | delete rootProject.buildDir
30 | }
31 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lfork/l.free-android/c855156fe649766570f03d6e0129a95fc7c530d3/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Mar 16 11:29:25 CST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------