Jelajahi Sumber

1:本来想给这个APP弄点干活,结果”干货集中营“的API调不通了,先上传代码吧

guiying712 9 tahun lalu
induk
melakukan
f34c0a4b7a
35 mengubah file dengan 880 tambahan dan 9 penghapusan
  1. 22 0
      app/src/main/java/com/guiying/androidmodulepattern/MainActivity.java
  2. 29 0
      app/src/main/java/com/guiying/androidmodulepattern/MyApplication.java
  3. 3 0
      app/src/main/res/values/strings.xml
  4. 5 0
      common/src/main/res/drawable/shape_loading_bg.xml
  5. 12 0
      common/src/main/res/layout/layout_load_error.xml
  6. 21 0
      common/src/main/res/layout/layout_load_more.xml
  7. 12 0
      common/src/main/res/layout/layout_load_no_more.xml
  8. 12 0
      common/src/main/res/layout/layout_load_progress.xml
  9. 7 0
      common/src/main/res/layout/layout_view_empty.xml
  10. 27 0
      common/src/main/res/layout/progress_dialog.xml
  11. 17 0
      common/src/main/res/layout/toolbar.xml
  12. 10 0
      common/src/main/res/values/strings.xml
  13. 1 1
      girls/src/main/debug/AndroidManifest.xml
  14. 10 0
      girls/src/main/java/com/guiying/girls/Constants.java
  15. 17 0
      girls/src/main/java/com/guiying/girls/data/GirlsDataSource.java
  16. 144 0
      girls/src/main/java/com/guiying/girls/data/bean/Girls.java
  17. 46 0
      girls/src/main/java/com/guiying/girls/data/parser/GirlsParser.java
  18. 46 0
      girls/src/main/java/com/guiying/girls/data/source/RemoteGirlsDataSource.java
  19. 10 2
      girls/src/main/java/com/guiying/girls/main/GirlsActivity.java
  20. 67 0
      girls/src/main/java/com/guiying/girls/main/GirlsAdapter.java
  21. 44 0
      girls/src/main/java/com/guiying/girls/main/GirlsContract.java
  22. 50 0
      girls/src/main/java/com/guiying/girls/main/GirlsPresenter.java
  23. 149 0
      girls/src/main/java/com/guiying/girls/main/GirlsView.java
  24. 1 1
      girls/src/main/release/AndroidManifest.xml
  25. 1 1
      girls/src/main/res/layout/activity_girls.xml
  26. 19 0
      girls/src/main/res/layout/item_girl.xml
  27. 17 0
      girls/src/main/res/layout/view_girls_content.xml
  28. 1 1
      news/src/main/debug/AndroidManifest.xml
  29. 2 1
      news/src/main/java/com/guiying/news/main/NewsActivity.java
  30. 23 0
      news/src/main/java/com/guiying/news/main/NewsContract.java
  31. 11 0
      news/src/main/java/com/guiying/news/main/NewsPresenter.java
  32. 13 0
      news/src/main/java/com/guiying/news/main/NewsView.java
  33. 29 0
      news/src/main/java/debug/NewsApplication.java
  34. 1 1
      news/src/main/release/AndroidManifest.xml
  35. 1 1
      news/src/main/res/layout/activity_news.xml

+ 22 - 0
app/src/main/java/com/guiying/androidmodulepattern/MainActivity.java

@@ -1,14 +1,20 @@
 package com.guiying.androidmodulepattern;
 
 import android.os.Bundle;
+import android.support.design.widget.Snackbar;
+import android.view.KeyEvent;
 import android.view.View;
 import android.widget.Button;
 
 import com.github.mzule.activityrouter.router.Routers;
 import com.guiying.common.base.BaseActivity;
+import com.guiying.common.base.BaseApplication;
 
 public class MainActivity extends BaseActivity implements View.OnClickListener {
 
+
+    private long exitTime = 0;
+
     protected Button newsButton;
     protected Button girlsButton;
 
@@ -31,4 +37,20 @@ public class MainActivity extends BaseActivity implements View.OnClickListener {
         }
     }
 
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
+            //两秒之内按返回键就会退出
+            if ((System.currentTimeMillis() - exitTime) > 2000) {
+                Snackbar.make(girlsButton, getString(R.string.app_exit_hint), Snackbar.LENGTH_LONG).show();
+                exitTime = System.currentTimeMillis();
+            } else {
+                BaseApplication.getIns().exitApp(this);
+            }
+            return true;
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
 }

+ 29 - 0
app/src/main/java/com/guiying/androidmodulepattern/MyApplication.java

@@ -2,6 +2,9 @@ package com.guiying.androidmodulepattern;
 
 import com.github.mzule.activityrouter.annotation.Modules;
 import com.guiying.common.base.BaseApplication;
+import com.guiying.common.http.HttpClient;
+import com.guiying.common.http.OnResultListener;
+import com.orhanobut.logger.Logger;
 
 /**
  * <p>类说明</p>
@@ -13,8 +16,34 @@ import com.guiying.common.base.BaseApplication;
 @Modules({"app", "girls", "news"})
 public class MyApplication extends BaseApplication {
 
+    String GAN_HUO_API = "http://gank.io/";
+
     @Override
     public void onCreate() {
         super.onCreate();
+        HttpClient client = new HttpClient.Builder()
+                .baseUrl(GAN_HUO_API)
+                .url("api/data")
+                .params("type", "福利")
+                .params("count", String.valueOf(20))
+                .params("page", String.valueOf(1))
+                .build();
+        client.post(new OnResultListener<String>() {
+
+            @Override
+            public void onSuccess(String result) {
+                Logger.e(result);
+            }
+
+            @Override
+            public void onError(int code, String message) {
+                Logger.e(message);
+            }
+
+            @Override
+            public void onFailure(String message) {
+                Logger.e(message);
+            }
+        });
     }
 }

+ 3 - 0
app/src/main/res/values/strings.xml

@@ -2,4 +2,7 @@
     <string name="app_name">AndroidModulePattern</string>
 
     <string name="global_scheme">module</string>
+
+    <string name="app_exit_hint">再按一次退出程序哦~</string>
+
 </resources>

+ 5 - 0
common/src/main/res/drawable/shape_loading_bg.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners android:radius="4dp" />
+    <solid android:color="@color/gray_66" />
+</shape>

+ 12 - 0
common/src/main/res/layout/layout_load_error.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?><!--easyrecyclerview库的公用布局-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="48dp">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:text="@string/load_error_resume" />
+</LinearLayout>

+ 21 - 0
common/src/main/res/layout/layout_load_more.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?><!--easyrecyclerview库的公用布局-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:gravity="center"
+    android:padding="8dp"
+    android:layout_width="match_parent"
+    android:layout_height="50dp">
+
+    <ProgressBar
+        android:layout_width="20dp"
+        android:layout_height="20dp" />
+
+    <TextView
+        android:text="@string/more_loading"
+        android:textSize="14sp"
+        android:layout_marginLeft="3dp"
+        android:layout_marginStart="3dp"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>

+ 12 - 0
common/src/main/res/layout/layout_load_no_more.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?><!--easyrecyclerview库的公用布局-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="48dp">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:text="@string/no_more" />
+</LinearLayout>

+ 12 - 0
common/src/main/res/layout/layout_load_progress.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?><!--easyrecyclerview库的公用布局-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ProgressBar
+        android:layout_gravity="center"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</FrameLayout>

+ 7 - 0
common/src/main/res/layout/layout_view_empty.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?><!--easyrecyclerview库的公用布局-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:text="@string/no_data"
+    android:textSize="18sp" />

+ 27 - 0
common/src/main/res/layout/progress_dialog.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:background="@drawable/shape_loading_bg"
+    android:gravity="center"
+    android:minHeight="@dimen/size_64dp"
+    android:minWidth="@dimen/size_110dp"
+    android:orientation="vertical"
+    android:padding="@dimen/size_10dp">
+
+    <ProgressBar
+        android:id="@+id/progress_bar"
+        android:layout_width="@dimen/size_30dp"
+        android:layout_height="@dimen/size_30dp" />
+
+    <TextView
+        android:id="@+id/tipTextView"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/size_10dp"
+        android:text="@string/loading"
+        android:textColor="@android:color/darker_gray"
+        android:textSize="@dimen/text_size_15sp" />
+
+</LinearLayout>

+ 17 - 0
common/src/main/res/layout/toolbar.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?><!--可以直接使用的toolbar-->
+<android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:theme="@style/AppTheme.AppBarOverlay">
+
+    <android.support.v7.widget.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="?attr/colorPrimary"
+        android:minHeight="?attr/actionBarSize"
+        android:theme="@style/Toolbar"
+        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
+
+</android.support.design.widget.AppBarLayout>

+ 10 - 0
common/src/main/res/values/strings.xml

@@ -3,4 +3,14 @@
 
     <string name="current_internet_invalid">当前网络未连接</string>
 
+    <!--loading-->
+    <string name="loading">载入中···</string>
+
+    <!--EasyRecyclerView库的公用布局-->
+    <string name="more_loading">加载中…</string>
+    <string name="no_more">没有更多了</string>
+    <string name="load_error_resume">加载出错,点击重试</string>
+    <string name="more">更多</string>
+    <string name="no_data">暂无数据</string>
+
 </resources>

+ 1 - 1
girls/src/main/debug/AndroidManifest.xml

@@ -10,7 +10,7 @@
         android:supportsRtl="true"
         android:theme="@style/AppTheme">
         <activity
-            android:name=".GirlsActivity"
+            android:name=".main.GirlsActivity"
             android:screenOrientation="portrait">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />

+ 10 - 0
girls/src/main/java/com/guiying/girls/Constants.java

@@ -0,0 +1,10 @@
+package com.guiying.girls;
+
+/**
+ * 保存项目中用到的常量
+ */
+public interface Constants {
+
+    String GAN_HUO_API = "http://gank.io/";
+
+}

+ 17 - 0
girls/src/main/java/com/guiying/girls/data/GirlsDataSource.java

@@ -0,0 +1,17 @@
+package com.guiying.girls.data;
+
+import com.guiying.girls.data.parser.GirlsParser;
+
+public interface GirlsDataSource {
+
+    interface LoadGirlsCallback {
+
+        void onGirlsLoaded(GirlsParser girlsParser);
+
+        void onDataNotAvailable();
+    }
+
+    void getGirls(int page, int size, LoadGirlsCallback callback);
+
+    void getGirl(LoadGirlsCallback callback);
+}

+ 144 - 0
girls/src/main/java/com/guiying/girls/data/bean/Girls.java

@@ -0,0 +1,144 @@
+package com.guiying.girls.data.bean;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * <p>类说明</p>
+ *
+ * @author 张华洋 2017/2/22 20:51
+ * @version V1.2.0
+ * @name Girls
+ */
+
+
+public class Girls implements Parcelable {
+
+    private String _id;
+    private String createdAt;
+    private String desc;
+    private String publishedAt;
+    private String source;
+    private String type;
+    private String url;
+    private boolean used;
+    private String who;
+
+    public void set_id(String _id) {
+        this._id = _id;
+    }
+
+    public void setCreatedAt(String createdAt) {
+        this.createdAt = createdAt;
+    }
+
+    public void setDesc(String desc) {
+        this.desc = desc;
+    }
+
+    public void setPublishedAt(String publishedAt) {
+        this.publishedAt = publishedAt;
+    }
+
+    public void setSource(String source) {
+        this.source = source;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public void setUsed(boolean used) {
+        this.used = used;
+    }
+
+    public void setWho(String who) {
+        this.who = who;
+    }
+
+    public String get_id() {
+        return _id;
+    }
+
+    public String getCreatedAt() {
+        return createdAt;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public String getPublishedAt() {
+        return publishedAt;
+    }
+
+    public String getSource() {
+        return source;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public boolean isUsed() {
+        return used;
+    }
+
+    public String getWho() {
+        return who;
+    }
+
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(this._id);
+        dest.writeString(this.createdAt);
+        dest.writeString(this.desc);
+        dest.writeString(this.publishedAt);
+        dest.writeString(this.source);
+        dest.writeString(this.type);
+        dest.writeString(this.url);
+        dest.writeByte(this.used ? (byte) 1 : (byte) 0);
+        dest.writeString(this.who);
+    }
+
+    public Girls() {
+    }
+
+    protected Girls(Parcel in) {
+        this._id = in.readString();
+        this.createdAt = in.readString();
+        this.desc = in.readString();
+        this.publishedAt = in.readString();
+        this.source = in.readString();
+        this.type = in.readString();
+        this.url = in.readString();
+        this.used = in.readByte() != 0;
+        this.who = in.readString();
+    }
+
+    public static final Creator<Girls> CREATOR = new Creator<Girls>() {
+        @Override
+        public Girls createFromParcel(Parcel source) {
+            return new Girls(source);
+        }
+
+        @Override
+        public Girls[] newArray(int size) {
+            return new Girls[size];
+        }
+    };
+}

+ 46 - 0
girls/src/main/java/com/guiying/girls/data/parser/GirlsParser.java

@@ -0,0 +1,46 @@
+package com.guiying.girls.data.parser;
+
+import com.guiying.girls.data.bean.Girls;
+
+import java.util.List;
+
+public class GirlsParser {
+
+    /**
+     * error : false
+     * results : [{"_id":"5771d5eb421aa931ddcc50d6","createdAt":"2016-06-28T09:42:03.761Z","desc":"Dagger2图文完全教程","publishedAt":"2016-06-28T11:33:25.276Z","source":"web","type":"Android","url":"https://github.com/luxiaoming/dagger2Demo","used":true,"who":"代码GG陆晓明"},{"_id":"5771c9ca421aa931ca5a7e59","createdAt":"2016-06-28T08:50:18.731Z","desc":"Android Design 设计模板","publishedAt":"2016-06-28T11:33:25.276Z","source":"chrome","type":"Android","url":"https://github.com/andreasschrade/android-design-template","used":true,"who":"代码家"}]
+     */
+
+    private boolean error;
+    /**
+     * _id : 5771d5eb421aa931ddcc50d6
+     * createdAt : 2016-06-28T09:42:03.761Z
+     * desc : Dagger2图文完全教程
+     * publishedAt : 2016-06-28T11:33:25.276Z
+     * source : web
+     * type : Android
+     * url : https://github.com/luxiaoming/dagger2Demo
+     * used : true
+     * who : 代码GG陆晓明
+     */
+
+    private List<Girls> results;
+
+    public void setError(boolean error) {
+        this.error = error;
+    }
+
+    public void setResults(List<Girls> results) {
+        this.results = results;
+    }
+
+    public boolean isError() {
+        return error;
+    }
+
+    public List<Girls> getResults() {
+        return results;
+    }
+
+
+}

+ 46 - 0
girls/src/main/java/com/guiying/girls/data/source/RemoteGirlsDataSource.java

@@ -0,0 +1,46 @@
+package com.guiying.girls.data.source;
+
+
+import com.guiying.common.http.HttpClient;
+import com.guiying.common.http.OnResultListener;
+import com.guiying.girls.Constants;
+import com.guiying.girls.data.GirlsDataSource;
+import com.guiying.girls.data.parser.GirlsParser;
+
+
+public class RemoteGirlsDataSource implements GirlsDataSource {
+
+    @Override
+    public void getGirls(int page, int size, final LoadGirlsCallback callback) {
+        HttpClient client = new HttpClient.Builder()
+                .baseUrl(Constants.GAN_HUO_API)
+                .url("api/data")
+                .params("type", "福利")
+                .params("count", String.valueOf(page))
+                .params("page", String.valueOf(size))
+                .build();
+        client.post(new OnResultListener<GirlsParser>() {
+
+            @Override
+            public void onSuccess(GirlsParser result) {
+                callback.onGirlsLoaded(result);
+            }
+
+            @Override
+            public void onError(int code, String message) {
+                callback.onDataNotAvailable();
+            }
+
+            @Override
+            public void onFailure(String message) {
+                callback.onDataNotAvailable();
+            }
+        });
+    }
+
+    @Override
+    public void getGirl(final LoadGirlsCallback callback) {
+        getGirls(1, 1, callback);
+    }
+
+}

+ 10 - 2
girls/src/main/java/com/guiying/girls/GirlsActivity.java → girls/src/main/java/com/guiying/girls/main/GirlsActivity.java

@@ -1,18 +1,23 @@
-package com.guiying.girls;
+package com.guiying.girls.main;
 
 import android.os.Bundle;
 import android.support.v7.app.ActionBar;
 
 import com.github.mzule.activityrouter.annotation.Router;
 import com.guiying.common.base.BaseActivity;
+import com.guiying.girls.R;
 
 @Router("girls")
 public class GirlsActivity extends BaseActivity {
 
+    private GirlsView mView;
+    private GirlsContract.Presenter mPresenter;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_girls);
+        mView = new GirlsView(this);
+        setContentView(mView);
 
         //标题栏设置
         ActionBar actionBar = getSupportActionBar();
@@ -20,6 +25,9 @@ public class GirlsActivity extends BaseActivity {
             actionBar.setDisplayHomeAsUpEnabled(true);
             actionBar.setTitle(R.string.girls_activity_title);
         }
+
+        mPresenter = new GirlsPresenter(mView);
+        mPresenter.start();
     }
 
 

+ 67 - 0
girls/src/main/java/com/guiying/girls/main/GirlsAdapter.java

@@ -0,0 +1,67 @@
+package com.guiying.girls.main;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.engine.DiskCacheStrategy;
+import com.guiying.girls.R;
+import com.guiying.girls.data.bean.Girls;
+import com.jude.easyrecyclerview.adapter.BaseViewHolder;
+import com.jude.easyrecyclerview.adapter.RecyclerArrayAdapter;
+
+public class GirlsAdapter extends RecyclerArrayAdapter<Girls> {
+
+    public OnMyItemClickListener mOnItemClickListener;
+
+    public GirlsAdapter(Context context) {
+        super(context);
+    }
+
+    @Override
+    public BaseViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) {
+        return new GirlsViewHolder(parent);
+    }
+
+    @Override
+    public void OnBindViewHolder(final BaseViewHolder holder, final int position) {
+        super.OnBindViewHolder(holder, position);
+        holder.itemView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mOnItemClickListener != null) {
+                    mOnItemClickListener.onItemClick(position, holder);
+                }
+            }
+        });
+    }
+
+    private class GirlsViewHolder extends BaseViewHolder<Girls> {
+
+        private ImageView image;
+
+        private GirlsViewHolder(ViewGroup parent) {
+            super(parent, R.layout.item_girl);
+            image = $(R.id.girl_img);
+        }
+
+        @Override
+        public void setData(Girls data) {
+            super.setData(data);
+            Glide.with(getContext())
+                    .load(data.getUrl())
+                    .diskCacheStrategy(DiskCacheStrategy.SOURCE)
+                    .into(image);
+        }
+    }
+
+    public interface OnMyItemClickListener {
+        void onItemClick(int position, BaseViewHolder holder);
+    }
+
+    public void setOnMyItemClickListener(OnMyItemClickListener listener) {
+        this.mOnItemClickListener = listener;
+    }
+}

+ 44 - 0
girls/src/main/java/com/guiying/girls/main/GirlsContract.java

@@ -0,0 +1,44 @@
+package com.guiying.girls.main;
+
+import com.guiying.common.base.BasePresenter;
+import com.guiying.common.base.BaseView;
+import com.guiying.girls.data.bean.Girls;
+
+import java.util.List;
+
+/**
+ * <p>类说明</p>
+ *
+ * @author 张华洋 2017/2/22 20:33
+ * @version V1.2.0
+ * @name GirlsContract
+ */
+public interface GirlsContract {
+
+    interface View extends BaseView<Presenter> {
+
+        /**
+         * View 的存活状态
+         *
+         * @return true or false
+         */
+        boolean isActive();
+
+        void refresh(List<Girls> data);
+
+        void load(List<Girls> data);
+
+        void showError();
+
+        void showNormal();
+
+    }
+
+    interface Presenter extends BasePresenter {
+
+        void getGirls(int page, int size, boolean isRefresh);
+
+    }
+
+
+}

+ 50 - 0
girls/src/main/java/com/guiying/girls/main/GirlsPresenter.java

@@ -0,0 +1,50 @@
+package com.guiying.girls.main;
+
+import com.guiying.girls.data.GirlsDataSource;
+import com.guiying.girls.data.parser.GirlsParser;
+import com.guiying.girls.data.source.RemoteGirlsDataSource;
+
+/**
+ * <p>类说明</p>
+ *
+ * @author 张华洋 2017/2/22 20:33
+ * @version V1.2.0
+ * @name GirlsPresenter
+ */
+public class GirlsPresenter implements GirlsContract.Presenter {
+
+    private GirlsContract.View mView;
+    private GirlsDataSource mDataSource;
+
+    public GirlsPresenter(GirlsContract.View view) {
+        mView = view;
+        mDataSource = new RemoteGirlsDataSource();
+    }
+
+    @Override
+    public void getGirls(int page, int size, final boolean isRefresh) {
+        mDataSource.getGirls(page, size, new GirlsDataSource.LoadGirlsCallback() {
+            @Override
+            public void onGirlsLoaded(GirlsParser girlsParser) {
+                if (isRefresh) {
+                    mView.refresh(girlsParser.getResults());
+                } else {
+                    mView.load(girlsParser.getResults());
+                }
+                mView.showNormal();
+            }
+
+            @Override
+            public void onDataNotAvailable() {
+                if (isRefresh) {
+                    mView.showError();
+                }
+            }
+        });
+    }
+
+    @Override
+    public void start() {
+        getGirls(1, 20, true);
+    }
+}

+ 149 - 0
girls/src/main/java/com/guiying/girls/main/GirlsView.java

@@ -0,0 +1,149 @@
+package com.guiying.girls.main;
+
+import android.content.Context;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.StaggeredGridLayoutManager;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewStub;
+import android.widget.FrameLayout;
+
+import com.guiying.girls.R;
+import com.guiying.girls.data.bean.Girls;
+import com.jude.easyrecyclerview.EasyRecyclerView;
+import com.jude.easyrecyclerview.adapter.BaseViewHolder;
+import com.jude.easyrecyclerview.adapter.RecyclerArrayAdapter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>类说明</p>
+ *
+ * @author 张华洋 2017/2/22 20:33
+ * @version V1.2.0
+ * @name GirlsView
+ */
+public class GirlsView extends FrameLayout implements GirlsContract.View, SwipeRefreshLayout.OnRefreshListener, RecyclerArrayAdapter.OnLoadMoreListener {
+
+    private GirlsContract.Presenter mPresenter;
+    private boolean mActive;
+
+    private EasyRecyclerView mGirlsRecyclerView;
+    private ViewStub mNetworkErrorLayout;
+    private View networkErrorView;
+    private GirlsAdapter mAdapter;
+    private ArrayList<Girls> mData;
+    private int page = 1;
+    private int size = 20;
+
+    public GirlsView(Context context) {
+        super(context);
+        initView();
+    }
+
+    public GirlsView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initView();
+    }
+
+
+    private void initView() {
+        inflate(getContext(), R.layout.view_girls_content, this);
+        mNetworkErrorLayout = (ViewStub) findViewById(R.id.network_error_layout);
+        mGirlsRecyclerView = (EasyRecyclerView) findViewById(R.id.girls_recycler_view);
+
+        mData = new ArrayList<>();
+        StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
+        mGirlsRecyclerView.setLayoutManager(staggeredGridLayoutManager);
+        mAdapter = new GirlsAdapter(getContext());
+
+        mGirlsRecyclerView.setAdapterWithProgress(mAdapter);
+
+        mAdapter.setMore(R.layout.layout_load_more, this);
+        mAdapter.setNoMore(R.layout.layout_load_no_more);
+        mAdapter.setError(R.layout.layout_load_error);
+        mAdapter.setOnMyItemClickListener(new GirlsAdapter.OnMyItemClickListener() {
+            @Override
+            public void onItemClick(int position, BaseViewHolder holder) {
+
+            }
+        });
+
+        mGirlsRecyclerView.setRefreshListener(this);
+
+        mActive = true;
+    }
+
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mActive = true;
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mActive = false;
+    }
+
+    @Override
+    public void setPresenter(GirlsContract.Presenter presenter) {
+        this.mPresenter = presenter;
+    }
+
+    @Override
+    public boolean isActive() {
+        return mActive;
+    }
+
+
+    @Override
+    public void refresh(List<Girls> data) {
+        mData.clear();
+        mData.addAll(data);
+        mAdapter.clear();
+        mAdapter.addAll(data);
+    }
+
+    @Override
+    public void load(List<Girls> data) {
+        mData.addAll(data);
+        mAdapter.addAll(data);
+    }
+
+    @Override
+    public void showError() {
+        mGirlsRecyclerView.showError();
+
+        if (networkErrorView != null) {
+            networkErrorView.setVisibility(View.VISIBLE);
+            return;
+        }
+
+        networkErrorView = mNetworkErrorLayout.inflate();
+    }
+
+    @Override
+    public void showNormal() {
+        if (networkErrorView != null) {
+            networkErrorView.setVisibility(View.GONE);
+        }
+    }
+
+
+    @Override
+    public void onLoadMore() {
+        if (mData.size() % 20 == 0) {
+            page++;
+            mPresenter.getGirls(page, size, false);
+        }
+    }
+
+    @Override
+    public void onRefresh() {
+        mPresenter.getGirls(1, size, true);
+        page = 1;
+    }
+}

+ 1 - 1
girls/src/main/release/AndroidManifest.xml

@@ -3,7 +3,7 @@
 
     <application android:theme="@style/AppTheme">
         <activity
-            android:name=".GirlsActivity"
+            android:name=".main.GirlsActivity"
             android:screenOrientation="portrait" />
     </application>
 

+ 1 - 1
girls/src/main/res/layout/activity_girls.xml

@@ -4,7 +4,7 @@
     android:id="@+id/activity_girls"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    tools:context="com.guiying.girls.GirlsActivity">
+    tools:context="com.guiying.girls.main.GirlsActivity">
 
     <TextView
         android:layout_width="wrap_content"

+ 19 - 0
girls/src/main/res/layout/item_girl.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="#FFFFFF"
+    android:orientation="vertical"
+    android:paddingLeft="1dp"
+    android:paddingRight="1dp"
+    android:paddingTop="2dp">
+
+    <ImageView
+        android:id="@+id/girl_img"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:adjustViewBounds="true"
+        android:minHeight="150dp"
+        android:scaleType="fitCenter" />
+
+</LinearLayout>

+ 17 - 0
girls/src/main/res/layout/view_girls_content.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <ViewStub
+        android:id="@+id/network_error_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout="@layout/layout_load_error" />
+
+    <com.jude.easyrecyclerview.EasyRecyclerView
+        android:id="@+id/girls_recycler_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:layout_progress="@layout/layout_load_progress"
+        app:scrollbarStyle="insideOverlay" />
+</merge>

+ 1 - 1
news/src/main/debug/AndroidManifest.xml

@@ -10,7 +10,7 @@
         android:supportsRtl="true"
         android:theme="@style/AppTheme">
         <activity
-            android:name=".NewsActivity"
+            android:name=".main.NewsActivity"
             android:screenOrientation="portrait">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />

+ 2 - 1
news/src/main/java/com/guiying/news/NewsActivity.java → news/src/main/java/com/guiying/news/main/NewsActivity.java

@@ -1,10 +1,11 @@
-package com.guiying.news;
+package com.guiying.news.main;
 
 import android.os.Bundle;
 import android.support.v7.app.ActionBar;
 
 import com.github.mzule.activityrouter.annotation.Router;
 import com.guiying.common.base.BaseActivity;
+import com.guiying.news.R;
 
 @Router("news")
 public class NewsActivity extends BaseActivity {

+ 23 - 0
news/src/main/java/com/guiying/news/main/NewsContract.java

@@ -0,0 +1,23 @@
+package com.guiying.news.main;
+
+import com.guiying.common.base.BasePresenter;
+import com.guiying.common.base.BaseView;
+
+/**
+ * <p>类说明</p>
+ *
+ * @author 张华洋 2017/2/22 20:33
+ * @version V1.2.0
+ * @name NewsContract
+ */
+public interface NewsContract {
+
+    interface View extends BaseView<Presenter> {
+
+    }
+
+    interface Presenter extends BasePresenter {
+
+    }
+
+}

+ 11 - 0
news/src/main/java/com/guiying/news/main/NewsPresenter.java

@@ -0,0 +1,11 @@
+package com.guiying.news.main;
+
+/**
+ * <p>类说明</p>
+ *
+ * @author 张华洋 2017/2/22 20:33
+ * @version V1.2.0
+ * @name GirlsPresenter
+ */
+public class NewsPresenter {
+}

+ 13 - 0
news/src/main/java/com/guiying/news/main/NewsView.java

@@ -0,0 +1,13 @@
+package com.guiying.news.main;
+
+/**
+ * <p>类说明</p>
+ *
+ * @author 张华洋 2017/2/22 20:33
+ * @version V1.2.0
+ * @name GirlsView
+ */
+
+
+public class NewsView {
+}

+ 29 - 0
news/src/main/java/debug/NewsApplication.java

@@ -1,6 +1,9 @@
 package debug;
 
 import com.guiying.common.base.BaseApplication;
+import com.guiying.common.http.HttpClient;
+import com.guiying.common.http.OnResultListener;
+import com.orhanobut.logger.Logger;
 
 /**
  * <p>类说明</p>
@@ -11,8 +14,34 @@ import com.guiying.common.base.BaseApplication;
  */
 public class NewsApplication extends BaseApplication {
 
+    String GAN_HUO_API = "http://gank.io/";
+
     @Override
     public void onCreate() {
         super.onCreate();
+        HttpClient client = new HttpClient.Builder()
+                .baseUrl(GAN_HUO_API)
+                .url("api/data")
+                .params("type", "福利")
+                .params("count", String.valueOf(20))
+                .params("page", String.valueOf(1))
+                .build();
+        client.post(new OnResultListener<String>() {
+
+            @Override
+            public void onSuccess(String result) {
+                Logger.e(result);
+            }
+
+            @Override
+            public void onError(int code, String message) {
+                Logger.e(message);
+            }
+
+            @Override
+            public void onFailure(String message) {
+                Logger.e(message);
+            }
+        });
     }
 }

+ 1 - 1
news/src/main/release/AndroidManifest.xml

@@ -3,7 +3,7 @@
 
     <application android:theme="@style/AppTheme">
         <activity
-            android:name=".NewsActivity"
+            android:name=".main.NewsActivity"
             android:screenOrientation="portrait" />
     </application>
 

+ 1 - 1
news/src/main/res/layout/activity_news.xml

@@ -4,7 +4,7 @@
     android:id="@+id/activity_news"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    tools:context="com.guiying.news.NewsActivity">
+    tools:context="com.guiying.news.main.NewsActivity">
 
     <TextView
         android:layout_width="wrap_content"