├── .gitignore ├── .idea └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── opensource │ │ └── zjt │ │ └── rxnews │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java-gen │ │ └── com │ │ │ └── rxnews │ │ │ └── greendao │ │ │ ├── DBHelper.java │ │ │ ├── DaoMaster.java │ │ │ ├── DaoSession.java │ │ │ ├── Greenrxnews.java │ │ │ └── GreenrxnewsDao.java │ ├── java │ │ └── opensource │ │ │ └── zjt │ │ │ └── rxnews │ │ │ ├── base │ │ │ ├── AppService.java │ │ │ ├── BaseActivity.java │ │ │ ├── BaseApplication.java │ │ │ ├── BaseFragment.java │ │ │ └── RxBus.java │ │ │ ├── bean │ │ │ ├── BaseModel.java │ │ │ ├── ImageModel.java │ │ │ └── NewsModel.java │ │ │ ├── event │ │ │ ├── Event.java │ │ │ └── NewsEvent.java │ │ │ ├── model │ │ │ ├── INewsModel.java │ │ │ ├── ImageModelImpl.java │ │ │ ├── ImageModelInterface.java │ │ │ └── NewsModelImpl.java │ │ │ ├── net │ │ │ ├── Constant.java │ │ │ ├── NewsCallback.java │ │ │ ├── NewsClient.java │ │ │ ├── NewsFactory.java │ │ │ ├── NewsResponse.java │ │ │ ├── RxNewsApi.java │ │ │ └── RxNewsImageApi.java │ │ │ ├── presenter │ │ │ ├── ImagePresenter.java │ │ │ ├── ImagePresenterImpl.java │ │ │ ├── NewsDetailPresenter.java │ │ │ ├── NewsDetailPresenterImpl.java │ │ │ ├── NewsPresenter.java │ │ │ └── NewsPresenterImpl.java │ │ │ ├── rxmethod │ │ │ └── RxNews.java │ │ │ ├── ui │ │ │ ├── activity │ │ │ │ ├── MainActivity.java │ │ │ │ └── NewsDetailActivity.java │ │ │ └── fragment │ │ │ │ ├── DummyContent.java │ │ │ │ ├── ImageAdapter.java │ │ │ │ ├── ImageFragment.java │ │ │ │ ├── MyItemRecyclerViewAdapter.java │ │ │ │ ├── NewsFragment.java │ │ │ │ └── NewsListFragment.java │ │ │ ├── utils │ │ │ └── AppUtils.java │ │ │ └── view │ │ │ ├── ImageViewInterface.java │ │ │ ├── NewsDetailView.java │ │ │ └── NewsView.java │ └── res │ │ ├── drawable-v21 │ │ ├── ic_menu_camera.xml │ │ ├── ic_menu_gallery.xml │ │ ├── ic_menu_manage.xml │ │ ├── ic_menu_send.xml │ │ ├── ic_menu_share.xml │ │ └── ic_menu_slideshow.xml │ │ ├── drawable-xxhdpi │ │ ├── ic_image_loadfail.png │ │ └── ic_image_loading.png │ │ ├── drawable │ │ └── side_nav_bar.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_news_detail.xml │ │ ├── app_bar_main.xml │ │ ├── content_main.xml │ │ ├── footer.xml │ │ ├── fragment_image.xml │ │ ├── fragment_item.xml │ │ ├── fragment_item_list.xml │ │ ├── fragment_news.xml │ │ ├── item_image.xml │ │ └── nav_header_main.xml │ │ ├── menu │ │ ├── activity_main_drawer.xml │ │ └── main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── drawables.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── opensource │ └── zjt │ └── rxnews │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradlew ├── gradlew.bat ├── rxnew_greendao ├── .gitignore ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── example │ └── DaoGeneration.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | /app/build 2 | /gradle 3 | /.idea 4 | /.gradle 5 | *.iml 6 | .gradle 7 | /local.properties 8 | /.idea/workspace.xml 9 | /.idea/libraries 10 | .DS_Store 11 | /build 12 | /captures 13 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RxNews 2 | # 使用RxJava 框架的新闻客户端 3 | #特点 4 | * Retrofit2.0+RxJava+RxBus+GreenDao的使用 5 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "opensource.zjt.rxnews" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | sourceSets { 21 | main { 22 | java.srcDirs = ['src/main/java', 'src/main/java-gen'] 23 | } 24 | } 25 | } 26 | 27 | dependencies { 28 | compile fileTree(dir: 'libs', include: ['*.jar']) 29 | testCompile 'junit:junit:4.12' 30 | compile 'com.android.support:appcompat-v7:23.1.1' 31 | compile 'com.android.support:design:23.1.1' 32 | compile 'com.android.support:cardview-v7:23.1.1' 33 | compile 'com.squareup.okhttp:okhttp:2.5.0' 34 | compile 'com.github.zhaokaiqiang.klog:library:1.1.0' 35 | compile 'com.github.bumptech.glide:glide:3.5.2' 36 | compile 'com.jakewharton:butterknife:7.0.1' 37 | compile 'io.reactivex:rxandroid:1.0.1' 38 | compile 'io.reactivex:rxjava:1.0.16' 39 | compile 'io.reactivex:rxjava-math:1.0.0' 40 | compile 'com.jakewharton.rxbinding:rxbinding:0.3.0' 41 | compile 'com.squareup.retrofit:retrofit:2.0.0-beta3' 42 | compile 'com.google.code.gson:gson:2.4' 43 | compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' 44 | compile 'com.thefinestartist:finestwebview:1.1.2' 45 | compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' 46 | compile 'com.android.support:support-v4:23.1.1' 47 | compile 'com.android.support:recyclerview-v7:23.1.1' 48 | compile 'com.squareup.okhttp:logging-interceptor:2.6.0' 49 | compile 'de.greenrobot:greendao:2.0.0' 50 | } 51 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/Adele/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/opensource/zjt/rxnews/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/java-gen/com/rxnews/greendao/DBHelper.java: -------------------------------------------------------------------------------- 1 | package com.rxnews.greendao; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.util.Config; 6 | 7 | import de.greenrobot.dao.query.QueryBuilder; 8 | 9 | /** 10 | * Created by JianTao on 16/1/25. 11 | * Copyright © 2015 impetusconsulting. All rights reserved 12 | */ 13 | public class DBHelper { 14 | private static DBHelper sInstance; 15 | private static final Object WATCH_DOG = new Object(); 16 | private final String DB_NAME = "rxnews_db"; 17 | private SQLiteDatabase db; 18 | private DaoSession daoSession; 19 | 20 | public static DBHelper getInstance(Context context) { 21 | synchronized (WATCH_DOG) { 22 | if (sInstance == null) { 23 | sInstance = new DBHelper(context); 24 | } 25 | return sInstance; 26 | } 27 | } 28 | 29 | private DBHelper(Context context) { 30 | DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, DB_NAME, null); 31 | db = helper.getWritableDatabase(); 32 | // 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。 33 | DaoMaster daoMaster = new DaoMaster(db); 34 | daoSession = daoMaster.newSession(); 35 | if (Config.DEBUG) { 36 | QueryBuilder.LOG_SQL = true; 37 | QueryBuilder.LOG_VALUES = true; 38 | } 39 | } 40 | 41 | public DaoSession getDaoSession() { 42 | return daoSession; 43 | } 44 | 45 | public SQLiteDatabase getDb() { 46 | return db; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java-gen/com/rxnews/greendao/DaoMaster.java: -------------------------------------------------------------------------------- 1 | package com.rxnews.greendao; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.database.sqlite.SQLiteDatabase.CursorFactory; 6 | import android.database.sqlite.SQLiteOpenHelper; 7 | import android.util.Log; 8 | import de.greenrobot.dao.AbstractDaoMaster; 9 | import de.greenrobot.dao.identityscope.IdentityScopeType; 10 | 11 | import com.rxnews.greendao.GreenrxnewsDao; 12 | 13 | // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. 14 | /** 15 | * Master of DAO (schema version 1): knows all DAOs. 16 | */ 17 | public class DaoMaster extends AbstractDaoMaster { 18 | public static final int SCHEMA_VERSION = 1; 19 | 20 | /** Creates underlying database table using DAOs. */ 21 | public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) { 22 | GreenrxnewsDao.createTable(db, ifNotExists); 23 | } 24 | 25 | /** Drops underlying database table using DAOs. */ 26 | public static void dropAllTables(SQLiteDatabase db, boolean ifExists) { 27 | GreenrxnewsDao.dropTable(db, ifExists); 28 | } 29 | 30 | public static abstract class OpenHelper extends SQLiteOpenHelper { 31 | 32 | public OpenHelper(Context context, String name, CursorFactory factory) { 33 | super(context, name, factory, SCHEMA_VERSION); 34 | } 35 | 36 | @Override 37 | public void onCreate(SQLiteDatabase db) { 38 | Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION); 39 | createAllTables(db, false); 40 | } 41 | } 42 | 43 | /** WARNING: Drops all table on Upgrade! Use only during development. */ 44 | public static class DevOpenHelper extends OpenHelper { 45 | public DevOpenHelper(Context context, String name, CursorFactory factory) { 46 | super(context, name, factory); 47 | } 48 | 49 | @Override 50 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 51 | Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables"); 52 | dropAllTables(db, true); 53 | onCreate(db); 54 | } 55 | } 56 | 57 | public DaoMaster(SQLiteDatabase db) { 58 | super(db, SCHEMA_VERSION); 59 | registerDaoClass(GreenrxnewsDao.class); 60 | } 61 | 62 | public DaoSession newSession() { 63 | return new DaoSession(db, IdentityScopeType.Session, daoConfigMap); 64 | } 65 | 66 | public DaoSession newSession(IdentityScopeType type) { 67 | return new DaoSession(db, type, daoConfigMap); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java-gen/com/rxnews/greendao/DaoSession.java: -------------------------------------------------------------------------------- 1 | package com.rxnews.greendao; 2 | 3 | import android.database.sqlite.SQLiteDatabase; 4 | 5 | import java.util.Map; 6 | 7 | import de.greenrobot.dao.AbstractDao; 8 | import de.greenrobot.dao.AbstractDaoSession; 9 | import de.greenrobot.dao.identityscope.IdentityScopeType; 10 | import de.greenrobot.dao.internal.DaoConfig; 11 | 12 | import com.rxnews.greendao.Greenrxnews; 13 | 14 | import com.rxnews.greendao.GreenrxnewsDao; 15 | 16 | // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. 17 | 18 | /** 19 | * {@inheritDoc} 20 | * 21 | * @see de.greenrobot.dao.AbstractDaoSession 22 | */ 23 | public class DaoSession extends AbstractDaoSession { 24 | 25 | private final DaoConfig greenrxnewsDaoConfig; 26 | 27 | private final GreenrxnewsDao greenrxnewsDao; 28 | 29 | public DaoSession(SQLiteDatabase db, IdentityScopeType type, Map>, DaoConfig> 30 | daoConfigMap) { 31 | super(db); 32 | 33 | greenrxnewsDaoConfig = daoConfigMap.get(GreenrxnewsDao.class).clone(); 34 | greenrxnewsDaoConfig.initIdentityScope(type); 35 | 36 | greenrxnewsDao = new GreenrxnewsDao(greenrxnewsDaoConfig, this); 37 | 38 | registerDao(Greenrxnews.class, greenrxnewsDao); 39 | } 40 | 41 | public void clear() { 42 | greenrxnewsDaoConfig.getIdentityScope().clear(); 43 | } 44 | 45 | public GreenrxnewsDao getGreenrxnewsDao() { 46 | return greenrxnewsDao; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java-gen/com/rxnews/greendao/Greenrxnews.java: -------------------------------------------------------------------------------- 1 | package com.rxnews.greendao; 2 | 3 | // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. Enable "keep" sections if you want to edit. 4 | /** 5 | * Entity mapped to table "GREENRXNEWS". 6 | */ 7 | public class Greenrxnews { 8 | 9 | private Long id; 10 | private String newslist; 11 | private String type; 12 | 13 | public Greenrxnews() { 14 | } 15 | 16 | public Greenrxnews(Long id) { 17 | this.id = id; 18 | } 19 | 20 | public Greenrxnews(Long id, String newslist, String type) { 21 | this.id = id; 22 | this.newslist = newslist; 23 | this.type = type; 24 | } 25 | 26 | public Long getId() { 27 | return id; 28 | } 29 | 30 | public void setId(Long id) { 31 | this.id = id; 32 | } 33 | 34 | public String getNewslist() { 35 | return newslist; 36 | } 37 | 38 | public void setNewslist(String newslist) { 39 | this.newslist = newslist; 40 | } 41 | 42 | public String getType() { 43 | return type; 44 | } 45 | 46 | public void setType(String type) { 47 | this.type = type; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java-gen/com/rxnews/greendao/GreenrxnewsDao.java: -------------------------------------------------------------------------------- 1 | package com.rxnews.greendao; 2 | 3 | import android.database.Cursor; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.database.sqlite.SQLiteStatement; 6 | 7 | import de.greenrobot.dao.AbstractDao; 8 | import de.greenrobot.dao.Property; 9 | import de.greenrobot.dao.internal.DaoConfig; 10 | 11 | import com.rxnews.greendao.Greenrxnews; 12 | 13 | // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. 14 | /** 15 | * DAO for table "GREENRXNEWS". 16 | */ 17 | public class GreenrxnewsDao extends AbstractDao { 18 | 19 | public static final String TABLENAME = "GREENRXNEWS"; 20 | 21 | /** 22 | * Properties of entity Greenrxnews.
23 | * Can be used for QueryBuilder and for referencing column names. 24 | */ 25 | public static class Properties { 26 | public final static Property Id = new Property(0, Long.class, "id", true, "_id"); 27 | public final static Property Newslist = new Property(1, String.class, "newslist", false, "NEWSLIST"); 28 | public final static Property Type = new Property(2, String.class, "type", false, "TYPE"); 29 | }; 30 | 31 | 32 | public GreenrxnewsDao(DaoConfig config) { 33 | super(config); 34 | } 35 | 36 | public GreenrxnewsDao(DaoConfig config, DaoSession daoSession) { 37 | super(config, daoSession); 38 | } 39 | 40 | /** Creates the underlying database table. */ 41 | public static void createTable(SQLiteDatabase db, boolean ifNotExists) { 42 | String constraint = ifNotExists? "IF NOT EXISTS ": ""; 43 | db.execSQL("CREATE TABLE " + constraint + "\"GREENRXNEWS\" (" + // 44 | "\"_id\" INTEGER PRIMARY KEY ," + // 0: id 45 | "\"NEWSLIST\" TEXT," + // 1: newslist 46 | "\"TYPE\" TEXT);"); // 2: type 47 | } 48 | 49 | /** Drops the underlying database table. */ 50 | public static void dropTable(SQLiteDatabase db, boolean ifExists) { 51 | String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"GREENRXNEWS\""; 52 | db.execSQL(sql); 53 | } 54 | 55 | /** @inheritdoc */ 56 | @Override 57 | protected void bindValues(SQLiteStatement stmt, Greenrxnews entity) { 58 | stmt.clearBindings(); 59 | 60 | Long id = entity.getId(); 61 | if (id != null) { 62 | stmt.bindLong(1, id); 63 | } 64 | 65 | String newslist = entity.getNewslist(); 66 | if (newslist != null) { 67 | stmt.bindString(2, newslist); 68 | } 69 | 70 | String type = entity.getType(); 71 | if (type != null) { 72 | stmt.bindString(3, type); 73 | } 74 | } 75 | 76 | /** @inheritdoc */ 77 | @Override 78 | public Long readKey(Cursor cursor, int offset) { 79 | return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0); 80 | } 81 | 82 | /** @inheritdoc */ 83 | @Override 84 | public Greenrxnews readEntity(Cursor cursor, int offset) { 85 | Greenrxnews entity = new Greenrxnews( // 86 | cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id 87 | cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // newslist 88 | cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2) // type 89 | ); 90 | return entity; 91 | } 92 | 93 | /** @inheritdoc */ 94 | @Override 95 | public void readEntity(Cursor cursor, Greenrxnews entity, int offset) { 96 | entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0)); 97 | entity.setNewslist(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1)); 98 | entity.setType(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2)); 99 | } 100 | 101 | /** @inheritdoc */ 102 | @Override 103 | protected Long updateKeyAfterInsert(Greenrxnews entity, long rowId) { 104 | entity.setId(rowId); 105 | return rowId; 106 | } 107 | 108 | /** @inheritdoc */ 109 | @Override 110 | public Long getKey(Greenrxnews entity) { 111 | if(entity != null) { 112 | return entity.getId(); 113 | } else { 114 | return null; 115 | } 116 | } 117 | 118 | /** @inheritdoc */ 119 | @Override 120 | protected boolean isEntityUpdateable() { 121 | return true; 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/base/AppService.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.base; 2 | 3 | import com.google.gson.Gson; 4 | import com.rxnews.greendao.DBHelper; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.concurrent.ExecutorService; 9 | import java.util.concurrent.Executors; 10 | 11 | import opensource.zjt.rxnews.net.NewsFactory; 12 | import opensource.zjt.rxnews.net.RxNewsApi; 13 | import opensource.zjt.rxnews.rxmethod.RxNews; 14 | import rx.subscriptions.CompositeSubscription; 15 | 16 | /** 17 | * Created by JianTao on 16/1/20. 18 | * Copyright © 2015 impetusconsulting. All rights reserved 19 | */ 20 | public class AppService { 21 | private static AppService instance = new AppService(); 22 | private static RxNewsApi rxNewsApi; 23 | private static ExecutorService sSingleThreadExecutor; 24 | private static DBHelper dbHelper; 25 | private static Gson sGson; 26 | 27 | private Map compositeSubscriptionMap; 28 | 29 | public AppService() { 30 | } 31 | 32 | public void initService() { 33 | compositeSubscriptionMap = new HashMap<>(); 34 | sGson=new Gson(); 35 | sSingleThreadExecutor = Executors.newSingleThreadExecutor(); 36 | sSingleThreadExecutor.execute(new Runnable() { 37 | @Override 38 | public void run() { 39 | rxNewsApi = NewsFactory.getRxNewsApi(); 40 | dbHelper = DBHelper.getInstance(BaseApplication.getmContext()); 41 | } 42 | }); 43 | } 44 | 45 | public static Gson getsGson() { 46 | return sGson; 47 | } 48 | 49 | public void addCompositeSub(int taskId) { 50 | CompositeSubscription compositeSubscription; 51 | if (compositeSubscriptionMap.get(taskId) == null) { 52 | compositeSubscription = new CompositeSubscription(); 53 | compositeSubscriptionMap.put(taskId, compositeSubscription); 54 | } 55 | } 56 | 57 | public static DBHelper getDbHelper() { 58 | return dbHelper; 59 | } 60 | 61 | public void removeCompositeSub(int taskId) { 62 | CompositeSubscription compositeSubscription; 63 | if (compositeSubscriptionMap != null && compositeSubscriptionMap.get(taskId) != null) { 64 | compositeSubscription = compositeSubscriptionMap.get(taskId); 65 | compositeSubscription.unsubscribe(); 66 | compositeSubscriptionMap.remove(taskId); 67 | } 68 | } 69 | 70 | public CompositeSubscription getCompositeSubscription(int taskId) { 71 | CompositeSubscription compositeSubscription; 72 | if (compositeSubscriptionMap.get(taskId) == null) { 73 | compositeSubscription = new CompositeSubscription(); 74 | compositeSubscriptionMap.put(taskId, compositeSubscription); 75 | } else { 76 | compositeSubscription = compositeSubscriptionMap.get(taskId); 77 | } 78 | return compositeSubscription; 79 | } 80 | 81 | public void initNews(int taskId, String type) { 82 | getCompositeSubscription(taskId).add(RxNews.initNews(type)); 83 | } 84 | 85 | public void updataNews(int taskId, String type) { 86 | getCompositeSubscription(taskId).add(RxNews.updataNews(type, 1)); 87 | } 88 | 89 | public Map getCompositeSubscriptionMap() { 90 | return compositeSubscriptionMap; 91 | } 92 | 93 | public static AppService getInstance() { 94 | return instance; 95 | } 96 | 97 | public static RxNewsApi getRxNewsApi() { 98 | return rxNewsApi; 99 | } 100 | 101 | public static ExecutorService getsSingleThreadExecutor() { 102 | return sSingleThreadExecutor; 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.base; 2 | 3 | import android.os.Bundle; 4 | import android.os.PersistableBundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | import butterknife.ButterKnife; 8 | 9 | /** 10 | * Created by JianTao on 16/1/21. 11 | * Copyright © 2015 impetusconsulting. All rights reserved 12 | */ 13 | public class BaseActivity extends AppCompatActivity{ 14 | @Override 15 | public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) { 16 | super.onCreate(savedInstanceState, persistentState); 17 | AppService.getInstance().addCompositeSub(getTaskId()); 18 | ButterKnife.bind(this); 19 | } 20 | 21 | @Override 22 | protected void onDestroy() { 23 | super.onDestroy(); 24 | AppService.getInstance().removeCompositeSub(getTaskId()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/base/BaseApplication.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.base; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | /** 7 | * Created by JianTao on 16/1/21. 8 | * Copyright © 2015 impetusconsulting. All rights reserved 9 | */ 10 | public class BaseApplication extends Application { 11 | private static Context mContext; 12 | 13 | @Override 14 | public void onCreate() { 15 | super.onCreate(); 16 | mContext = getApplicationContext(); 17 | AppService.getInstance().initService(); 18 | } 19 | 20 | public static Context getmContext() { 21 | return mContext; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.base; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | 7 | /** 8 | * Created by JianTao on 16/1/21. 9 | * Copyright © 2015 impetusconsulting. All rights reserved 10 | */ 11 | public class BaseFragment extends Fragment { 12 | private int mTaskId; 13 | @Override 14 | public void onCreate(@Nullable Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | mTaskId = getActivity().getTaskId(); 17 | } 18 | 19 | protected int getmTaskId() { 20 | return mTaskId; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/base/RxBus.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.base; 2 | 3 | import rx.Observable; 4 | import rx.subjects.PublishSubject; 5 | import rx.subjects.SerializedSubject; 6 | import rx.subjects.Subject; 7 | 8 | /** 9 | * Created by JianTao on 16/1/20. 10 | * Copyright © 2015 impetusconsulting. All rights reserved 11 | */ 12 | public class RxBus { 13 | private static volatile RxBus instance; 14 | 15 | public RxBus() { 16 | } 17 | 18 | public static RxBus getInstance() { 19 | if (instance == null) { 20 | synchronized (RxBus.class) { 21 | if (instance == null) { 22 | instance = new RxBus(); 23 | } 24 | } 25 | } 26 | return instance; 27 | } 28 | 29 | private final Subject _bus = new SerializedSubject<>(PublishSubject.create()); 30 | 31 | public void send(Object o) { 32 | _bus.onNext(o); 33 | } 34 | 35 | public Observable toObservable() { 36 | return _bus; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/bean/BaseModel.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.bean; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | /** 7 | * Created by JianTao on 16/1/10. 8 | * Copyright © 2015 impetusconsulting. All rights reserved 9 | */ 10 | public class BaseModel implements Parcelable { 11 | protected BaseModel(Parcel in) { 12 | } 13 | 14 | public BaseModel() { 15 | } 16 | 17 | @Override 18 | public int describeContents() { 19 | return 0; 20 | } 21 | 22 | @Override 23 | public void writeToParcel(Parcel dest, int flags) { 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/bean/ImageModel.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.bean; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by JianTao on 16/1/25. 7 | * Copyright © 2015 impetusconsulting. All rights reserved 8 | */ 9 | public class ImageModel { 10 | 11 | /** 12 | * code : 200 13 | * msg : ok 14 | * newslist : [{"hottime":"2015-07-17","title":"那个抱走王明涵的,你上微信吗?看完这个你会心软吗?","description":"中国传统文化","picUrl":"http://zxpic.gtimg.com/infonew/0/wechat_pics_-667708.jpg/640","url":"http://mp.weixin.qq.com/s?__biz=MzA3OTg2NjEwNg==&idx=5&mid=209313388&sn=7e30bd2851d22f69580e202c31fc7ecf&qb_mtt_show_type=1"},{"hottime":"2015-06-12","title":"深悦地产风云榜丨房地产微信公众号一周榜单","description":"深悦会","picUrl":"http://zxpic.gtimg.com/infonew/0/wechat_pics_-530408.jpg/640","url":"http://mp.weixin.qq.com/s?__biz=MjM5NTI4NDk0Mg==&idx=4&mid=206963932&sn=595e66f68648b86fba04fbc3a58e623c&qb_mtt_show_type=1"},{"hottime":"2015-06-14","title":"一条微信向全世界宣告,这就是惠州!","description":"西子湖畔","picUrl":"http://zxpic.gtimg.com/infonew/0/wechat_pics_-536516.jpg/640","url":"http://mp.weixin.qq.com/s?__biz=MjM5NTAzMDQ0MA==&idx=1&mid=209423088&sn=fc5c230b38e4485a01bdc7693714047b&qb_mtt_show_type=1"},{"hottime":"2015-06-16","title":"昨晚微信朋友圈热传\u201c范冰冰良渚救小孩\u201d到底是怎么回事?","description":"都市快报","picUrl":"http://zxpic.gtimg.com/infonew/0/wechat_pics_-544298.jpg/640","url":"http://mp.weixin.qq.com/s?__biz=MTE1OTE0MzU2MQ==&idx=1&mid=210010983&sn=dbcb2ab25208c2e39b011d633a0e3e4e&qb_mtt_show_type=1"},{"hottime":"2015-06-16","title":"某女陪丈夫上山扫墓,因惧怕鞭炮,在车内,没事干,上微信.......","description":"教你学做魅力女人","picUrl":"http://zxpic.gtimg.com/infonew/0/wechat_pics_-543990.jpg/640","url":"http://mp.weixin.qq.com/s?__biz=MjM5MTIxMDcyMA==&idx=2&mid=210670409&sn=ec9cfea3bef0e518beccba8fe8a33984&qb_mtt_show_type=1"},{"hottime":"2015-06-19","title":"送给微信所有好友,端午前打开~","description":"点点星光","picUrl":"http://zxpic.gtimg.com/infonew/0/wechat_pics_-556398.jpg/640","url":"http://mp.weixin.qq.com/s?__biz=MzA3MTQxODAxOA==&idx=1&mid=218128244&sn=03b1e5f081406d61c8a78651347f56ee&qb_mtt_show_type=1"},{"hottime":"2015-07-18","title":"丈夫和别人的妻子一夜未归,妻子微信上写道.....","description":"教您做好女人","picUrl":"http://zxpic.gtimg.com/infonew/0/wechat_pics_-676445.jpg/640","url":"http://mp.weixin.qq.com/s?__biz=MjM5NzA4MjU4Ng==&idx=5&mid=211950986&sn=e8c49f694443248ae2d8f173dbf842d4&qb_mtt_show_type=1"},{"hottime":"2015-07-19","title":"【首个微信真人表情】校服angelababy欢迎下载","description":"Angelababy","picUrl":"http://zxpic.gtimg.com/infonew/0/wechat_pics_-676756.jpg/640","url":"http://mp.weixin.qq.com/s?__biz=Mjc2NzgzNDE4MA==&idx=1&mid=212423157&sn=e5b718581b79722a443bce1634f99bc7&qb_mtt_show_type=1"},{"hottime":"2015-07-19","title":"哪位高人写的微信,被传疯了!","description":"人生感悟励志语录","picUrl":"http://zxpic.gtimg.com/infonew/0/wechat_pics_-677119.jpg/640","url":"http://mp.weixin.qq.com/s?__biz=MjM5NTg1OTczMw==&idx=1&mid=749183945&sn=9d0675d52557ba9717fc9e1f4e85da7c&qb_mtt_show_type=1"},{"hottime":"2015-07-20","title":"子洲遭灾之际,榆林银杏酒店一员工在微信圈辱骂子洲人,引发众怒","description":"陕北山丹丹花","picUrl":"http://zxpic.gtimg.com/infonew/0/wechat_pics_-681387.jpg/640","url":"http://mp.weixin.qq.com/s?__biz=MzA4ODg4OTA3Mw==&idx=1&mid=208913836&sn=43192f9a1d85fe3f88a26c7dcaa0e640&qb_mtt_show_type=1"}] 15 | */ 16 | 17 | private int code; 18 | private String msg; 19 | /** 20 | * hottime : 2015-07-17 21 | * title : 那个抱走王明涵的,你上微信吗?看完这个你会心软吗? 22 | * description : 中国传统文化 23 | * picUrl : http://zxpic.gtimg.com/infonew/0/wechat_pics_-667708.jpg/640 24 | * url : http://mp.weixin.qq.com/s?__biz=MzA3OTg2NjEwNg==&idx=5&mid=209313388&sn=7e30bd2851d22f69580e202c31fc7ecf&qb_mtt_show_type=1 25 | */ 26 | 27 | private List newslist; 28 | 29 | public void setCode(int code) { 30 | this.code = code; 31 | } 32 | 33 | public void setMsg(String msg) { 34 | this.msg = msg; 35 | } 36 | 37 | public void setNewslist(List newslist) { 38 | this.newslist = newslist; 39 | } 40 | 41 | public int getCode() { 42 | return code; 43 | } 44 | 45 | public String getMsg() { 46 | return msg; 47 | } 48 | 49 | public List getNewslist() { 50 | return newslist; 51 | } 52 | 53 | public static class NewsImagelistEntity { 54 | private String hottime; 55 | private String title; 56 | private String description; 57 | private String picUrl; 58 | private String url; 59 | 60 | public void setHottime(String hottime) { 61 | this.hottime = hottime; 62 | } 63 | 64 | public void setTitle(String title) { 65 | this.title = title; 66 | } 67 | 68 | public void setDescription(String description) { 69 | this.description = description; 70 | } 71 | 72 | public void setPicUrl(String picUrl) { 73 | this.picUrl = picUrl; 74 | } 75 | 76 | public void setUrl(String url) { 77 | this.url = url; 78 | } 79 | 80 | public String getHottime() { 81 | return hottime; 82 | } 83 | 84 | public String getTitle() { 85 | return title; 86 | } 87 | 88 | public String getDescription() { 89 | return description; 90 | } 91 | 92 | public String getPicUrl() { 93 | return picUrl; 94 | } 95 | 96 | public String getUrl() { 97 | return url; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/bean/NewsModel.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.bean; 2 | 3 | import android.os.Parcel; 4 | 5 | import java.io.Serializable; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * Created by JianTao on 16/1/10. 11 | * Copyright © 2015 impetusconsulting. All rights reserved 12 | */ 13 | public class NewsModel extends BaseModel { 14 | /** 15 | * code : 200 16 | * msg : ok 17 | * newslist : [{"ctime":"2016-01-09 21:51","title":"苹果iPhone自动弹iCloud登录窗?小心已被黑","description":"苹果iPhone自动弹iCloud登录窗?小心已被黑...","picUrl":"http://mat1.gtimg.com/tech/00Jamesdu/2014/index/remark/2.png","url":"http://tech.qq.com/a/20160109/031741.htm"},{"ctime":"2016-01-09 21:15","title":"这种技术让手机1分钟充满电","description":"这种技术让手机1分钟充满电...","picUrl":"http://img1.gtimg.com/tech/pics/hv1/159/252/2001/130179444.jpg","url":"http://tech.qq.com/a/20160109/031312.htm"},{"ctime":"2016-01-09 16:32","title":"世界首个合法电子人:体内植入科技产品","description":"世界首个合法电子人:体内植入科技产品...","picUrl":"http://img1.gtimg.com/tech/pics/hv1/218/248/2001/130178483.jpg","url":"http://tech.qq.com/a/20160109/025918.htm"},{"ctime":"2016-01-09 18:29","title":"迪斯尼CEO为何要求高管热衷科技?","description":"迪斯尼CEO为何要求高管热衷科技?...","picUrl":"http://mat1.gtimg.com/tech/00Jamesdu/2014/index/remark/2.png","url":"http://tech.qq.com/a/20160109/028558.htm"},{"ctime":"2016-01-09 18:42","title":"快播死了,但P2P是永恒的","description":"快播死了,但P2P是永恒的...","picUrl":"http://img1.gtimg.com/tech/pics/hv1/23/249/2001/130178543.jpg","url":"http://tech.qq.com/a/20160109/028705.htm"},{"ctime":"2016-01-09 08:27","title":"印度挤掉加拿大成为成人视频第三大观看国家","description":"印度挤掉加拿大成为成人视频第三大观看国家...","picUrl":"http://mat1.gtimg.com/tech/00Jamesdu/2014/index/remark/2.png","url":"http://tech.qq.com/a/20160109/009940.htm"},{"ctime":"2016-01-09 09:31","title":"猎鹰九号将再次发射 SpaceX三度挑战海上着陆","description":"猎鹰九号将再次发射 SpaceX三度挑战海上着陆...","picUrl":"http://img1.gtimg.com/tech/pics/hv1/137/204/2001/130167182.jpg","url":"http://tech.qq.com/a/20160109/012618.htm"},{"ctime":"2016-01-09 10:09","title":"吹牛过度 明星无人机企业CES展跳票","description":"吹牛过度 明星无人机企业CES展跳票...","picUrl":"http://mat1.gtimg.com/tech/00Jamesdu/2014/index/remark/2.png","url":"http://tech.qq.com/a/20160109/014182.htm"},{"ctime":"2016-01-09 09:21","title":"iPhone 7有三种设计方案正在测试","description":"iPhone 7有三种设计方案正在测试...","picUrl":"http://img1.gtimg.com/tech/pics/hv1/58/214/2001/130169653.jpg","url":"http://tech.qq.com/a/20160109/012276.htm"},{"ctime":"2016-01-09 10:24","title":"不专业的审判无法得到公正的结果","description":"不专业的审判无法得到公正的结果...","picUrl":"http://mat1.gtimg.com/tech/00Jamesdu/2014/index/remark/2.png","url":"http://tech.qq.com/a/20160109/014631.htm"}] 18 | */ 19 | 20 | private int code; 21 | private String msg; 22 | /** 23 | * ctime : 2016-01-09 21:51 24 | * title : 苹果iPhone自动弹iCloud登录窗?小心已被黑 25 | * description : 苹果iPhone自动弹iCloud登录窗?小心已被黑... 26 | * picUrl : http://mat1.gtimg.com/tech/00Jamesdu/2014/index/remark/2.png 27 | * url : http://tech.qq.com/a/20160109/031741.htm 28 | */ 29 | 30 | private List newslist; 31 | 32 | public void setCode(int code) { 33 | this.code = code; 34 | } 35 | 36 | public void setMsg(String msg) { 37 | this.msg = msg; 38 | } 39 | 40 | public void setNewslist(List newslist) { 41 | this.newslist = newslist; 42 | } 43 | 44 | public int getCode() { 45 | return code; 46 | } 47 | 48 | public String getMsg() { 49 | return msg; 50 | } 51 | 52 | public List getNewslist() { 53 | return newslist; 54 | } 55 | 56 | public static class NewslistEntity extends BaseModel { 57 | private String ctime; 58 | private String title; 59 | private String description; 60 | private String picUrl; 61 | private String url; 62 | 63 | public void setCtime(String ctime) { 64 | this.ctime = ctime; 65 | } 66 | 67 | public void setTitle(String title) { 68 | this.title = title; 69 | } 70 | 71 | public void setDescription(String description) { 72 | this.description = description; 73 | } 74 | 75 | public void setPicUrl(String picUrl) { 76 | this.picUrl = picUrl; 77 | } 78 | 79 | public void setUrl(String url) { 80 | this.url = url; 81 | } 82 | 83 | public String getCtime() { 84 | return ctime; 85 | } 86 | 87 | public String getTitle() { 88 | return title; 89 | } 90 | 91 | public String getDescription() { 92 | return description; 93 | } 94 | 95 | public String getPicUrl() { 96 | return picUrl; 97 | } 98 | 99 | public String getUrl() { 100 | return url; 101 | } 102 | 103 | @Override 104 | public String toString() { 105 | return "NewslistEntity{" + 106 | "ctime='" + ctime + '\'' + 107 | ", title='" + title + '\'' + 108 | ", description='" + description + '\'' + 109 | ", picUrl='" + picUrl + '\'' + 110 | ", url='" + url + '\'' + 111 | '}'; 112 | } 113 | 114 | @Override 115 | public int describeContents() { 116 | return 0; 117 | } 118 | 119 | @Override 120 | public void writeToParcel(Parcel dest, int flags) { 121 | super.writeToParcel(dest, flags); 122 | dest.writeString(this.ctime); 123 | dest.writeString(this.title); 124 | dest.writeString(this.description); 125 | dest.writeString(this.picUrl); 126 | dest.writeString(this.url); 127 | } 128 | 129 | public NewslistEntity() { 130 | } 131 | 132 | protected NewslistEntity(Parcel in) { 133 | super(in); 134 | this.ctime = in.readString(); 135 | this.title = in.readString(); 136 | this.description = in.readString(); 137 | this.picUrl = in.readString(); 138 | this.url = in.readString(); 139 | } 140 | 141 | public static final Creator CREATOR = new Creator() { 142 | public NewslistEntity createFromParcel(Parcel source) { 143 | return new NewslistEntity(source); 144 | } 145 | 146 | public NewslistEntity[] newArray(int size) { 147 | return new NewslistEntity[size]; 148 | } 149 | }; 150 | } 151 | 152 | @Override 153 | public int describeContents() { 154 | return 0; 155 | } 156 | 157 | @Override 158 | public void writeToParcel(Parcel dest, int flags) { 159 | super.writeToParcel(dest, flags); 160 | dest.writeInt(this.code); 161 | dest.writeString(this.msg); 162 | dest.writeList(this.newslist); 163 | } 164 | 165 | public NewsModel() { 166 | super(); 167 | } 168 | 169 | protected NewsModel(Parcel in) { 170 | super(in); 171 | this.code = in.readInt(); 172 | this.msg = in.readString(); 173 | this.newslist = new ArrayList(); 174 | in.readList(this.newslist, List.class.getClassLoader()); 175 | } 176 | 177 | public static final Creator CREATOR = new Creator() { 178 | public NewsModel createFromParcel(Parcel source) { 179 | return new NewsModel(source); 180 | } 181 | 182 | public NewsModel[] newArray(int size) { 183 | return new NewsModel[size]; 184 | } 185 | }; 186 | 187 | @Override 188 | public String toString() { 189 | return "NewsModel{" + 190 | "code=" + code + 191 | ", msg='" + msg + '\'' + 192 | ", newslist=" + newslist.size() + 193 | '}'; 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/event/Event.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.event; 2 | 3 | import opensource.zjt.rxnews.net.Constant; 4 | 5 | /** 6 | * Created by JianTao on 16/1/20. 7 | * Copyright © 2015 impetusconsulting. All rights reserved 8 | */ 9 | public class Event { 10 | protected Constant.Result mEventResult; 11 | 12 | public Constant.Result getmEventResult() { 13 | return mEventResult; 14 | } 15 | 16 | public void setmEventResult(Constant.Result mEventResult) { 17 | this.mEventResult = mEventResult; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/event/NewsEvent.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.event; 2 | 3 | import opensource.zjt.rxnews.bean.NewsModel; 4 | import opensource.zjt.rxnews.net.Constant; 5 | 6 | /** 7 | * Created by JianTao on 16/1/20. 8 | * Copyright © 2015 impetusconsulting. All rights reserved 9 | */ 10 | public class NewsEvent extends Event { 11 | private NewsModel news; 12 | private Constant.GetNewsWay getNewsWay; 13 | private String newsType; 14 | 15 | public NewsEvent(NewsModel news, Constant.GetNewsWay getNewsWay, String newsType) { 16 | this.news = news; 17 | this.getNewsWay = getNewsWay; 18 | this.newsType = newsType; 19 | } 20 | 21 | public NewsModel getNews() { 22 | return news; 23 | } 24 | 25 | public Constant.GetNewsWay getGetNewsWay() { 26 | return getNewsWay; 27 | } 28 | 29 | public String getNewsType() { 30 | return newsType; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/model/INewsModel.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.model; 2 | 3 | /** 4 | * Created by JianTao on 16/1/21. 5 | * Copyright © 2015 impetusconsulting. All rights reserved 6 | */ 7 | public interface INewsModel { 8 | void loadNews(int type,int num); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/model/ImageModelImpl.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.model; 2 | 3 | import java.util.List; 4 | 5 | import opensource.zjt.rxnews.bean.ImageModel; 6 | import opensource.zjt.rxnews.net.NewsCallback; 7 | import opensource.zjt.rxnews.net.NewsFactory; 8 | import opensource.zjt.rxnews.net.NewsResponse; 9 | import opensource.zjt.rxnews.rxmethod.RxNews; 10 | import retrofit.Call; 11 | 12 | /** 13 | */ 14 | public class ImageModelImpl implements ImageModelInterface { 15 | 16 | /** 17 | * 获取图片列表 18 | * @param listener 19 | */ 20 | @Override 21 | public void loadImageList(final OnLoadImageListListener listener) { 22 | 23 | Call call = NewsFactory.getRxNewsImageApi().loadImage(RxNews.KEY,10,1); 24 | call.enqueue(new NewsCallback() { 25 | @Override 26 | public void onCallback(NewsResponse response) { 27 | if (response.isSuccess()){ 28 | listener.onSuccess(response.getmResult().getNewslist()); 29 | }else { 30 | listener.onFailure(response.getErrorMessage()); 31 | } 32 | } 33 | }); 34 | } 35 | 36 | public interface OnLoadImageListListener { 37 | void onSuccess(List list); 38 | void onFailure(String msg); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/model/ImageModelInterface.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.model; 2 | 3 | /** 4 | * Description : 5 | * Author : lauren 6 | * Email : lauren.liuling@gmail.com 7 | * Blog : http://www.liuling123.com 8 | * Date : 15/12/22 9 | */ 10 | public interface ImageModelInterface { 11 | void loadImageList(ImageModelImpl.OnLoadImageListListener listener); 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/model/NewsModelImpl.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.model; 2 | 3 | import opensource.zjt.rxnews.base.AppService; 4 | import opensource.zjt.rxnews.net.Constant; 5 | import opensource.zjt.rxnews.rxmethod.RxNews; 6 | 7 | /** 8 | * Created by JianTao on 16/1/21. 9 | * Copyright © 2015 impetusconsulting. All rights reserved 10 | */ 11 | public class NewsModelImpl implements INewsModel{ 12 | 13 | @Override 14 | public void loadNews(int type, int num) { 15 | RxNews.updataNews(getID(type), num); 16 | } 17 | private String getID(int type) { 18 | String id; 19 | switch (type) { 20 | case 0: 21 | id = Constant.NEWSTYPE_KEJI; 22 | break; 23 | case 1: 24 | id = Constant.NEWSTYPE_GUOJI; 25 | break; 26 | case 2: 27 | id = Constant.NEWSTYPE_SHEHUI; 28 | break; 29 | case 3: 30 | id = Constant.NEWSTYPE_TIYU; 31 | break; 32 | default: 33 | id = Constant.NEWSTYPE_KEJI; 34 | break; 35 | } 36 | return id; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/net/Constant.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.net; 2 | 3 | /** 4 | * Created by JianTao on 16/1/10. 5 | * Copyright © 2015 impetusconsulting. All rights reserved 6 | */ 7 | public class Constant { 8 | public static final String BASEURL = "http://api.huceo.com"; 9 | public static final int PAZE_SIZE = 10; 10 | public static final String NEWSDETAIL = "newsdetal"; 11 | public static final String NEWSTYPE_KEJI = "keji"; 12 | public static final String NEWSTYPE_TIYU = "tiyu"; 13 | public static final String NEWSTYPE_HUABIAN = "huabian"; 14 | public static final String NEWSTYPE_GUOJI = "world"; 15 | public static final String NEWSTYPE_SHEHUI = "social"; 16 | public static final String IMAGES_URL = "http://api.laifudao.com/open/tupian.json"; 17 | 18 | public enum GetNewsWay { 19 | INIT, UPDATA, LOADMORE; 20 | } 21 | 22 | public enum Result { 23 | SUCCESSS, FAIL, NORMAL; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/net/NewsCallback.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.net; 2 | 3 | 4 | import retrofit.Callback; 5 | import retrofit.Response; 6 | import retrofit.Retrofit; 7 | 8 | /** 9 | * Created by JianTao on 16/1/19. 10 | * Copyright © 2015 impetusconsulting. All rights reserved 11 | */ 12 | public abstract class NewsCallback implements Callback { 13 | 14 | @Override 15 | public void onResponse(Response response, Retrofit retrofit) { 16 | onCallback(new NewsResponse(response)); 17 | } 18 | 19 | @Override 20 | public void onFailure(Throwable t) { 21 | NewsResponse response = new NewsResponse<>(null); 22 | onCallback(response); 23 | } 24 | 25 | public abstract void onCallback(NewsResponse response); 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/net/NewsClient.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.net; 2 | 3 | import com.squareup.okhttp.CacheControl; 4 | import com.squareup.okhttp.Interceptor; 5 | import com.squareup.okhttp.OkHttpClient; 6 | import com.squareup.okhttp.Request; 7 | import com.squareup.okhttp.logging.HttpLoggingInterceptor; 8 | 9 | import java.io.IOException; 10 | 11 | import opensource.zjt.rxnews.base.BaseApplication; 12 | import opensource.zjt.rxnews.utils.AppUtils; 13 | import retrofit.GsonConverterFactory; 14 | import retrofit.Retrofit; 15 | import retrofit.RxJavaCallAdapterFactory; 16 | 17 | /** 18 | * Created by JianTao on 16/1/10. 19 | * Copyright © 2015 impetusconsulting. All rights reserved 20 | */ 21 | public class NewsClient { 22 | private static RxNewsApi rxNewsApi; 23 | private static RxNewsImageApi rxNewsImageApi; 24 | 25 | NewsClient() { 26 | } 27 | 28 | public RxNewsApi getRxNewsApi() { 29 | if (rxNewsApi == null) { 30 | HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 31 | logging.setLevel(HttpLoggingInterceptor.Level.BODY); 32 | OkHttpClient httpClient = new OkHttpClient(); 33 | httpClient.interceptors().add(logging); 34 | httpClient.interceptors().add(interceptor); 35 | Retrofit retrofit = new Retrofit.Builder().baseUrl(Constant.BASEURL) 36 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 37 | .addConverterFactory(GsonConverterFactory.create()) 38 | .build(); 39 | 40 | rxNewsApi = retrofit.create(RxNewsApi.class); 41 | } 42 | return rxNewsApi; 43 | } 44 | 45 | public RxNewsImageApi getRxNewsImageApi() { 46 | if (rxNewsImageApi == null) { 47 | HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 48 | logging.setLevel(HttpLoggingInterceptor.Level.BODY); 49 | OkHttpClient httpClient = new OkHttpClient(); 50 | httpClient.interceptors().add(logging); 51 | httpClient.interceptors().add(interceptor); 52 | Retrofit retrofit = new Retrofit.Builder().baseUrl(Constant.BASEURL) 53 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 54 | .addConverterFactory(GsonConverterFactory.create()) 55 | .build(); 56 | 57 | rxNewsImageApi = retrofit.create(RxNewsImageApi.class); 58 | } 59 | return rxNewsImageApi; 60 | } 61 | 62 | private Interceptor interceptor = new Interceptor() { 63 | @Override 64 | public com.squareup.okhttp.Response intercept(Chain chain) throws IOException { 65 | Request request = chain.request(); 66 | if (!AppUtils.isNetworkReachable(BaseApplication.getmContext())) { 67 | request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build(); 68 | } 69 | com.squareup.okhttp.Response response = chain.proceed(request); 70 | if (AppUtils.isNetworkReachable(BaseApplication.getmContext())) { 71 | int maxAge = 60 * 60; 72 | response.newBuilder() 73 | .removeHeader("Pragma") 74 | .header("Cache-Control", "public, max-age=" + maxAge) 75 | .build(); 76 | } else { 77 | int maxStale = 60 * 60 * 24 * 7; // 设置超时为一周 78 | response.newBuilder() 79 | .removeHeader("Pragma") 80 | .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) 81 | .build(); 82 | } 83 | return response; 84 | } 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/net/NewsFactory.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.net; 2 | 3 | /** 4 | * Created by JianTao on 16/1/10. 5 | * Copyright © 2015 impetusconsulting. All rights reserved 6 | */ 7 | public class NewsFactory { 8 | private static RxNewsApi rxNewsApi; 9 | private static RxNewsImageApi rxNewsImageApi; 10 | public NewsFactory() { 11 | 12 | } 13 | 14 | public static RxNewsApi getRxNewsApi() { 15 | synchronized (NewsFactory.class) { 16 | if (rxNewsApi == null) { 17 | NewsClient newsClient = new NewsClient(); 18 | rxNewsApi = newsClient.getRxNewsApi(); 19 | rxNewsImageApi = newsClient.getRxNewsImageApi(); 20 | } 21 | return rxNewsApi; 22 | } 23 | } 24 | 25 | public static RxNewsImageApi getRxNewsImageApi() { 26 | synchronized (NewsFactory.class) { 27 | if (rxNewsImageApi == null) { 28 | NewsClient newsClient = new NewsClient(); 29 | rxNewsApi = newsClient.getRxNewsApi(); 30 | rxNewsImageApi = newsClient.getRxNewsImageApi(); 31 | } 32 | return rxNewsImageApi; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/net/NewsResponse.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.net; 2 | 3 | import com.squareup.okhttp.ResponseBody; 4 | 5 | import java.io.IOException; 6 | 7 | import retrofit.Response; 8 | 9 | /** 10 | * Created by JianTao on 16/1/19. 11 | * Copyright © 2015 impetusconsulting. All rights reserved 12 | */ 13 | public class NewsResponse { 14 | private Response mResponse; 15 | private final T mResult; 16 | private ResponseBody mErrorBody; 17 | 18 | public NewsResponse(Response mResponse) { 19 | this.mResponse = mResponse; 20 | if (mResponse != null) { 21 | mResult = mResponse.body(); 22 | mErrorBody = mResponse.errorBody(); 23 | }else { 24 | mResult = null; 25 | mErrorBody = null; 26 | } 27 | } 28 | 29 | public T getmResult() { 30 | return mResult; 31 | } 32 | public String getErrorMessage() { 33 | if (mErrorBody != null) { 34 | try { 35 | return mErrorBody.string(); 36 | } catch (IOException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | return null; 41 | } 42 | public boolean isSuccess() { 43 | return mResult != null; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/net/RxNewsApi.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.net; 2 | 3 | import opensource.zjt.rxnews.bean.NewsModel; 4 | import retrofit.http.GET; 5 | import retrofit.http.Path; 6 | import retrofit.http.Query; 7 | import rx.Observable; 8 | 9 | /** 10 | * Created by JianTao on 16/1/10. 11 | * Copyright © 2015 impetusconsulting. All rights reserved 12 | */ 13 | public interface RxNewsApi { 14 | 15 | @GET("/{type}/other") 16 | Observable loadNews(@Path("type")String type, 17 | @Query("key") String key, 18 | @Query("num") String num, 19 | @Query("page")String page); 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/net/RxNewsImageApi.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.net; 2 | 3 | import opensource.zjt.rxnews.bean.ImageModel; 4 | import retrofit.Call; 5 | import retrofit.http.GET; 6 | import retrofit.http.Query; 7 | 8 | /** 9 | * Created by JianTao on 16/1/25. 10 | * Copyright © 2015 impetusconsulting. All rights reserved 11 | */ 12 | public interface RxNewsImageApi { 13 | @GET("/meinv/other") 14 | Call loadImage( 15 | @Query("key") String key, 16 | @Query("num") int num, 17 | @Query("page") int page); 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/presenter/ImagePresenter.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.presenter; 2 | 3 | /** 4 | * Created by JianTao on 16/1/25. 5 | * Copyright © 2015 impetusconsulting. All rights reserved 6 | */ 7 | public interface ImagePresenter { 8 | void loadImageList(); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/presenter/ImagePresenterImpl.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.presenter; 2 | 3 | 4 | 5 | import java.util.List; 6 | 7 | import opensource.zjt.rxnews.bean.ImageModel; 8 | import opensource.zjt.rxnews.model.ImageModelInterface; 9 | import opensource.zjt.rxnews.model.ImageModelImpl; 10 | import opensource.zjt.rxnews.view.ImageViewInterface; 11 | 12 | /** 13 | * Description : 14 | * Author : lauren 15 | * Email : lauren.liuling@gmail.com 16 | * Blog : http://www.liuling123.com 17 | * Date : 15/12/22 18 | */ 19 | public class ImagePresenterImpl implements ImagePresenter, ImageModelImpl.OnLoadImageListListener { 20 | 21 | private ImageModelInterface mImageModelInterface; 22 | private ImageViewInterface mImageView; 23 | 24 | public ImagePresenterImpl(ImageViewInterface imageView) { 25 | this.mImageModelInterface = new ImageModelImpl(); 26 | this.mImageView = imageView; 27 | } 28 | 29 | @Override 30 | public void loadImageList() { 31 | mImageView.showProgress(); 32 | mImageModelInterface.loadImageList(this); 33 | } 34 | 35 | @Override 36 | public void onSuccess(List list) { 37 | mImageView.addImages(list); 38 | mImageView.hideProgress(); 39 | } 40 | 41 | @Override 42 | public void onFailure(String msg) { 43 | mImageView.hideProgress(); 44 | mImageView.showLoadFailMsg(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/presenter/NewsDetailPresenter.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.presenter; 2 | 3 | /** 4 | * Created by JianTao on 16/1/21. 5 | * Copyright © 2015 impetusconsulting. All rights reserved 6 | */ 7 | public interface NewsDetailPresenter { 8 | void loadNewsDetail(String url); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/presenter/NewsDetailPresenterImpl.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.presenter; 2 | 3 | import android.content.Context; 4 | 5 | import opensource.zjt.rxnews.view.NewsDetailView; 6 | 7 | /** 8 | * Created by JianTao on 16/1/21. 9 | * Copyright © 2015 impetusconsulting. All rights reserved 10 | */ 11 | public class NewsDetailPresenterImpl implements NewsDetailPresenter { 12 | private Context context; 13 | private NewsDetailView newsDetailView; 14 | 15 | public NewsDetailPresenterImpl(Context context, NewsDetailView newsDetailView) { 16 | this.context = context; 17 | this.newsDetailView = newsDetailView; 18 | } 19 | 20 | @Override 21 | public void loadNewsDetail(String url) { 22 | newsDetailView.showProgress(); 23 | newsDetailView.showNewsDetailContent(url); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/presenter/NewsPresenter.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.presenter; 2 | 3 | /** 4 | * Created by JianTao on 16/1/21. 5 | * Copyright © 2015 impetusconsulting. All rights reserved 6 | */ 7 | public interface NewsPresenter { 8 | void loadNews(int type,int pageNum); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/presenter/NewsPresenterImpl.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.presenter; 2 | 3 | 4 | import opensource.zjt.rxnews.base.RxBus; 5 | import opensource.zjt.rxnews.event.NewsEvent; 6 | import opensource.zjt.rxnews.model.INewsModel; 7 | import opensource.zjt.rxnews.model.NewsModelImpl; 8 | import opensource.zjt.rxnews.net.Constant; 9 | import opensource.zjt.rxnews.view.NewsView; 10 | import rx.functions.Action1; 11 | 12 | /** 13 | * Created by JianTao on 16/1/21. 14 | * Copyright © 2015 impetusconsulting. All rights reserved 15 | */ 16 | public class NewsPresenterImpl implements NewsPresenter { 17 | 18 | private static final String TAG = "NewsPresenterImpl"; 19 | private NewsView newsView; 20 | private INewsModel newsModel; 21 | 22 | public NewsPresenterImpl(NewsView newsView) { 23 | this.newsView = newsView; 24 | this.newsModel = new NewsModelImpl(); 25 | RxBus.getInstance().toObservable().subscribe(newsEventAction); 26 | } 27 | 28 | @Override 29 | public void loadNews(int type, int pageNum) { 30 | if (pageNum == 0) { 31 | newsView.showProgress(); 32 | } 33 | newsModel.loadNews(type, pageNum); 34 | } 35 | 36 | private Action1 newsEventAction = new Action1() { 37 | @Override 38 | public void call(Object o) { 39 | if (o instanceof NewsEvent) { 40 | if (((NewsEvent) o).getmEventResult().equals(Constant.Result.SUCCESSS)) { 41 | if (newsView != null) { 42 | newsView.hideProgress(); 43 | newsView.addNew(((NewsEvent) o).getNews().getNewslist()); 44 | } 45 | } else if (((NewsEvent) o).getmEventResult().equals(Constant.Result.FAIL)) { 46 | if (newsView != null) { 47 | newsView.hideProgress(); 48 | newsView.showLoadFail(); 49 | } 50 | } 51 | } 52 | } 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/rxmethod/RxNews.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.rxmethod; 2 | 3 | import com.rxnews.greendao.Greenrxnews; 4 | import com.rxnews.greendao.GreenrxnewsDao; 5 | import com.socks.library.KLog; 6 | 7 | import java.util.List; 8 | 9 | import de.greenrobot.dao.query.DeleteQuery; 10 | import de.greenrobot.dao.query.Query; 11 | import opensource.zjt.rxnews.base.AppService; 12 | import opensource.zjt.rxnews.base.RxBus; 13 | import opensource.zjt.rxnews.event.NewsEvent; 14 | import opensource.zjt.rxnews.bean.NewsModel; 15 | import opensource.zjt.rxnews.net.Constant; 16 | import opensource.zjt.rxnews.net.NewsFactory; 17 | import rx.Observable; 18 | import rx.Subscriber; 19 | import rx.Subscription; 20 | import rx.android.schedulers.AndroidSchedulers; 21 | import rx.functions.Action1; 22 | import rx.schedulers.Schedulers; 23 | 24 | /** 25 | * Created by JianTao on 16/1/10. 26 | * Copyright © 2015 impetusconsulting. All rights reserved 27 | */ 28 | public class RxNews { 29 | public static final String KEY = "09fc0a2397154952297ea4b7e6b2646a"; 30 | 31 | public static Subscription initNews(final String newsType) { 32 | Subscription subscription = Observable.create(new Observable.OnSubscribe() { 33 | @Override 34 | public void call(Subscriber subscriber) { 35 | NewsModel newsModel = getCacheNew(newsType); 36 | subscriber.onNext(newsModel); 37 | subscriber.onCompleted(); 38 | } 39 | }).subscribeOn(Schedulers.io()).subscribe(new Action1() { 40 | @Override 41 | public void call(NewsModel news) { 42 | KLog.a("newsinit", news.toString()); 43 | NewsEvent newsEvent = new NewsEvent(news, Constant.GetNewsWay.INIT, newsType); 44 | if (news == null) { 45 | newsEvent.setmEventResult(Constant.Result.FAIL); 46 | } else { 47 | newsEvent.setmEventResult(Constant.Result.SUCCESSS); 48 | } 49 | RxBus.getInstance().send(newsEvent); 50 | } 51 | }, new Action1() { 52 | @Override 53 | public void call(Throwable throwable) { 54 | // KLog.a("newsError", throwable.toString()); 55 | NewsEvent newsEvent = new NewsEvent(new NewsModel(), Constant.GetNewsWay.INIT, newsType); 56 | newsEvent.setmEventResult(Constant.Result.FAIL); 57 | RxBus.getInstance().send(newsEvent); 58 | } 59 | }); 60 | return subscription; 61 | } 62 | 63 | public static Subscription updataNews(final String type, final int page) { 64 | Subscription subscription = NewsFactory.getRxNewsApi().loadNews(type, KEY, 10 + "", page + "") 65 | .subscribeOn(Schedulers.newThread()).doOnNext(new Action1() { 66 | @Override 67 | public void call(NewsModel news) { 68 | cacheNews(news, type); 69 | } 70 | }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1() { 71 | @Override 72 | public void call(NewsModel news) { 73 | KLog.a("newsupdata", news.toString()); 74 | NewsEvent newsEvent = new NewsEvent(news, Constant.GetNewsWay.UPDATA, type); 75 | if (news == null) { 76 | newsEvent.setmEventResult(Constant.Result.FAIL); 77 | } else { 78 | newsEvent.setmEventResult(Constant.Result.SUCCESSS); 79 | } 80 | RxBus.getInstance().send(newsEvent); 81 | } 82 | }, new Action1() { 83 | @Override 84 | public void call(Throwable throwable) { 85 | KLog.a("newsError", throwable.toString()); 86 | NewsEvent newsEvent = new NewsEvent(new NewsModel(), Constant.GetNewsWay.UPDATA, type); 87 | newsEvent.setmEventResult(Constant.Result.FAIL); 88 | RxBus.getInstance().send(newsEvent); 89 | } 90 | }); 91 | return subscription; 92 | 93 | } 94 | 95 | public static void cacheNews(NewsModel newsModel, String type) { 96 | GreenrxnewsDao greenrxnewsDao = AppService.getDbHelper().getDaoSession().getGreenrxnewsDao(); 97 | DeleteQuery deleteQuery = greenrxnewsDao.queryBuilder().where(GreenrxnewsDao.Properties.Type.eq(type)).buildDelete(); 98 | deleteQuery.executeDeleteWithoutDetachingEntities(); 99 | String news = AppService.getsGson().toJson(newsModel); 100 | Greenrxnews greenrxnews = new Greenrxnews(null, news, type); 101 | greenrxnewsDao.insert(greenrxnews); 102 | } 103 | 104 | private static NewsModel getCacheNew(String type) { 105 | NewsModel newsModel = null; 106 | GreenrxnewsDao greenrxnewsDao = AppService.getDbHelper().getDaoSession().getGreenrxnewsDao(); 107 | Query query = greenrxnewsDao.queryBuilder().where(GreenrxnewsDao.Properties.Type.eq(type)).build(); 108 | List greenrxnewses = query.list(); 109 | if (greenrxnewses != null && greenrxnewses.size() > 0) { 110 | newsModel = AppService.getsGson().fromJson(greenrxnewses.get(0).getNewslist(), NewsModel.class); 111 | } 112 | return newsModel; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/ui/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.ui.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.FloatingActionButton; 5 | import android.support.design.widget.NavigationView; 6 | import android.support.design.widget.Snackbar; 7 | import android.support.v4.view.GravityCompat; 8 | import android.support.v4.widget.DrawerLayout; 9 | import android.support.v7.app.ActionBarDrawerToggle; 10 | import android.support.v7.widget.Toolbar; 11 | import android.view.Menu; 12 | import android.view.MenuItem; 13 | import android.view.View; 14 | import android.widget.FrameLayout; 15 | import android.widget.Toast; 16 | 17 | import butterknife.Bind; 18 | import butterknife.ButterKnife; 19 | import opensource.zjt.rxnews.R; 20 | import opensource.zjt.rxnews.base.BaseActivity; 21 | import opensource.zjt.rxnews.ui.fragment.ImageFragment; 22 | import opensource.zjt.rxnews.ui.fragment.NewsFragment; 23 | 24 | public class MainActivity extends BaseActivity 25 | implements NavigationView.OnNavigationItemSelectedListener { 26 | 27 | @Bind(R.id.toolbar) 28 | Toolbar toolbar; 29 | @Bind(R.id.frame_content) 30 | FrameLayout frameContent; 31 | @Bind(R.id.fab) 32 | FloatingActionButton fab; 33 | @Bind(R.id.nav_view) 34 | NavigationView navView; 35 | @Bind(R.id.drawer_layout) 36 | DrawerLayout drawerLayout; 37 | 38 | @Override 39 | protected void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | setContentView(R.layout.activity_main); 42 | ButterKnife.bind(this); 43 | setSupportActionBar(toolbar); 44 | 45 | fab.setOnClickListener(new View.OnClickListener() { 46 | @Override 47 | public void onClick(View view) { 48 | Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 49 | .setAction("Action", null).show(); 50 | } 51 | }); 52 | 53 | ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( 54 | this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 55 | drawerLayout.setDrawerListener(toggle); 56 | toggle.syncState(); 57 | 58 | navView.setNavigationItemSelectedListener(this); 59 | getSupportFragmentManager().beginTransaction().replace(R.id.frame_content, new NewsFragment()).commit(); 60 | toolbar.setTitle("新闻"); 61 | } 62 | 63 | @Override 64 | public void onBackPressed() { 65 | DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 66 | if (drawer.isDrawerOpen(GravityCompat.START)) { 67 | drawer.closeDrawer(GravityCompat.START); 68 | } else { 69 | super.onBackPressed(); 70 | } 71 | } 72 | 73 | @Override 74 | public boolean onCreateOptionsMenu(Menu menu) { 75 | // Inflate the menu; this adds items to the action bar if it is present. 76 | getMenuInflater().inflate(R.menu.main, menu); 77 | return true; 78 | } 79 | 80 | @Override 81 | public boolean onOptionsItemSelected(MenuItem item) { 82 | // Handle action bar item clicks here. The action bar will 83 | // automatically handle clicks on the Home/Up button, so long 84 | // as you specify a parent activity in AndroidManifest.xml. 85 | int id = item.getItemId(); 86 | 87 | //noinspection SimplifiableIfStatement 88 | if (id == R.id.action_settings) { 89 | return true; 90 | } 91 | 92 | return super.onOptionsItemSelected(item); 93 | } 94 | 95 | @SuppressWarnings("StatementWithEmptyBody") 96 | @Override 97 | public boolean onNavigationItemSelected(MenuItem item) { 98 | // Handle navigation view item clicks here. 99 | int id = item.getItemId(); 100 | 101 | if (id == R.id.nav_news) { 102 | getSupportFragmentManager().beginTransaction().replace(R.id.frame_content, new NewsFragment()).commit(); 103 | } else if (id == R.id.nav_picture) { 104 | getSupportFragmentManager().beginTransaction().replace(R.id.frame_content, new ImageFragment()).commit(); 105 | } else if (id == R.id.nav_blog) { 106 | Toast.makeText(MainActivity.this, getResources().getString(R.string.no_dev), Toast.LENGTH_SHORT).show(); 107 | } else if (id == R.id.nav_setting) { 108 | Toast.makeText(MainActivity.this, getResources().getString(R.string.no_dev), Toast.LENGTH_SHORT).show(); 109 | 110 | } else if (id == R.id.nav_share) { 111 | Toast.makeText(MainActivity.this, getResources().getString(R.string.no_dev), Toast.LENGTH_SHORT).show(); 112 | 113 | } else if (id == R.id.nav_about) { 114 | Toast.makeText(MainActivity.this, getResources().getString(R.string.no_dev), Toast.LENGTH_SHORT).show(); 115 | 116 | } 117 | 118 | DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 119 | drawer.closeDrawer(GravityCompat.START); 120 | return true; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/ui/activity/NewsDetailActivity.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.ui.activity; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.os.Bundle; 5 | import android.support.design.widget.CollapsingToolbarLayout; 6 | import android.support.v7.widget.Toolbar; 7 | import android.view.View; 8 | import android.webkit.WebSettings; 9 | import android.webkit.WebView; 10 | import android.widget.ImageView; 11 | import android.widget.ProgressBar; 12 | 13 | import com.bumptech.glide.Glide; 14 | 15 | 16 | import butterknife.Bind; 17 | import butterknife.ButterKnife; 18 | import opensource.zjt.rxnews.R; 19 | import opensource.zjt.rxnews.base.BaseActivity; 20 | import opensource.zjt.rxnews.bean.NewsModel; 21 | import opensource.zjt.rxnews.net.Constant; 22 | import opensource.zjt.rxnews.presenter.NewsDetailPresenter; 23 | import opensource.zjt.rxnews.presenter.NewsDetailPresenterImpl; 24 | import opensource.zjt.rxnews.view.NewsDetailView; 25 | 26 | public class NewsDetailActivity extends BaseActivity implements NewsDetailView { 27 | 28 | @Bind(R.id.ivImage) 29 | ImageView ivImage; 30 | @Bind(R.id.toolbar) 31 | Toolbar toolbar; 32 | @Bind(R.id.collapsing_toolbar) 33 | CollapsingToolbarLayout collapsingToolbar; 34 | @Bind(R.id.progress) 35 | ProgressBar mProgressBar; 36 | @Bind(R.id.detail_webview) 37 | WebView detailWebview; 38 | private NewsModel.NewslistEntity mNews; 39 | private NewsDetailPresenter mNewsDetailPresenter; 40 | 41 | @SuppressLint("SetJavaScriptEnabled") 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | setContentView(R.layout.activity_news_detail); 46 | ButterKnife.bind(this); 47 | 48 | setSupportActionBar(toolbar); 49 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 50 | toolbar.setNavigationOnClickListener(new View.OnClickListener() { 51 | @Override 52 | public void onClick(View view) { 53 | onBackPressed(); 54 | } 55 | }); 56 | detailWebview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 57 | detailWebview.getSettings().setJavaScriptEnabled(true); 58 | detailWebview.setBackgroundColor(0); 59 | 60 | mNews = (NewsModel.NewslistEntity) getIntent().getParcelableExtra(Constant.NEWSDETAIL); 61 | 62 | CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar); 63 | collapsingToolbar.setTitle(mNews.getTitle()); 64 | 65 | Glide.with(this).load(mNews.getPicUrl()).into(ivImage); 66 | 67 | mNewsDetailPresenter = new NewsDetailPresenterImpl(getApplication(), this); 68 | mNewsDetailPresenter.loadNewsDetail(mNews.getUrl()); 69 | } 70 | 71 | @Override 72 | public void showNewsDetailContent(String detailUrl) { 73 | detailWebview.loadUrl(detailUrl); 74 | } 75 | 76 | @Override 77 | public void showProgress() { 78 | mProgressBar.setVisibility(View.VISIBLE); 79 | } 80 | 81 | @Override 82 | public void hideProgress() { 83 | mProgressBar.setVisibility(View.GONE); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/ui/fragment/DummyContent.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.ui.fragment; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * Helper class for providing sample content for user interfaces created by 10 | * Android template wizards. 11 | *

12 | * TODO: Replace all uses of this class before publishing your app. 13 | */ 14 | public class DummyContent { 15 | 16 | /** 17 | * An array of sample (dummy) items. 18 | */ 19 | public static final List ITEMS = new ArrayList(); 20 | 21 | /** 22 | * A map of sample (dummy) items, by ID. 23 | */ 24 | public static final Map ITEM_MAP = new HashMap(); 25 | 26 | private static final int COUNT = 25; 27 | 28 | static { 29 | // Add some sample items. 30 | for (int i = 1; i <= COUNT; i++) { 31 | addItem(createDummyItem(i)); 32 | } 33 | } 34 | 35 | private static void addItem(DummyItem item) { 36 | ITEMS.add(item); 37 | ITEM_MAP.put(item.id, item); 38 | } 39 | 40 | private static DummyItem createDummyItem(int position) { 41 | return new DummyItem(String.valueOf(position), "Item " + position, makeDetails(position)); 42 | } 43 | 44 | private static String makeDetails(int position) { 45 | StringBuilder builder = new StringBuilder(); 46 | builder.append("Details about Item: ").append(position); 47 | for (int i = 0; i < position; i++) { 48 | builder.append("\nMore details information here."); 49 | } 50 | return builder.toString(); 51 | } 52 | 53 | /** 54 | * A dummy item representing a piece of content. 55 | */ 56 | public static class DummyItem { 57 | public final String id; 58 | public final String content; 59 | public final String details; 60 | 61 | public DummyItem(String id, String content, String details) { 62 | this.id = id; 63 | this.content = content; 64 | this.details = details; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return content; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/ui/fragment/ImageAdapter.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.ui.fragment; 2 | 3 | import android.content.Context; 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.ImageView; 9 | import android.widget.TextView; 10 | 11 | import com.bumptech.glide.Glide; 12 | 13 | import java.util.List; 14 | 15 | import opensource.zjt.rxnews.R; 16 | import opensource.zjt.rxnews.bean.ImageModel; 17 | 18 | /** 19 | */ 20 | public class ImageAdapter extends RecyclerView.Adapter { 21 | 22 | private List mData; 23 | private Context mContext; 24 | 25 | private OnItemClickListener mOnItemClickListener; 26 | 27 | public ImageAdapter(Context context) { 28 | this.mContext = context; 29 | } 30 | 31 | public void setmDate(List data) { 32 | this.mData = data; 33 | this.notifyDataSetChanged(); 34 | } 35 | 36 | @Override 37 | public ImageAdapter.ItemViewHolder onCreateViewHolder(ViewGroup parent, 38 | int viewType) { 39 | View v = LayoutInflater.from(parent.getContext()) 40 | .inflate(R.layout.item_image, parent, false); 41 | ItemViewHolder vh = new ItemViewHolder(v); 42 | return vh; 43 | } 44 | 45 | @Override 46 | public void onBindViewHolder(ImageAdapter.ItemViewHolder holder, int position) { 47 | ImageModel.NewsImagelistEntity imageBean = mData.get(position); 48 | if(imageBean == null) { 49 | return; 50 | } 51 | holder.mTitle.setText(imageBean.getTitle()); 52 | Glide.with(mContext).load(imageBean.getPicUrl()).into(holder.mImage); 53 | } 54 | 55 | @Override 56 | public int getItemCount() { 57 | if(mData == null) { 58 | return 0; 59 | } 60 | return mData.size(); 61 | } 62 | 63 | public ImageModel.NewsImagelistEntity getItem(int position) { 64 | return mData == null ? null : mData.get(position); 65 | } 66 | 67 | public void setOnItemClickListener(OnItemClickListener onItemClickListener) { 68 | this.mOnItemClickListener = onItemClickListener; 69 | } 70 | 71 | public interface OnItemClickListener { 72 | void onItemClick(View view, int position); 73 | } 74 | 75 | public class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 76 | 77 | public TextView mTitle; 78 | public ImageView mImage; 79 | 80 | public ItemViewHolder(View v) { 81 | super(v); 82 | mTitle = (TextView) v.findViewById(R.id.tvTitle); 83 | mImage = (ImageView) v.findViewById(R.id.ivImage); 84 | v.setOnClickListener(this); 85 | } 86 | 87 | @Override 88 | public void onClick(View view) { 89 | if(mOnItemClickListener != null) { 90 | mOnItemClickListener.onItemClick(view, this.getPosition()); 91 | } 92 | } 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/ui/fragment/ImageFragment.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.ui.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v4.widget.SwipeRefreshLayout; 8 | import android.support.v7.widget.DefaultItemAnimator; 9 | import android.support.v7.widget.LinearLayoutManager; 10 | import android.support.v7.widget.RecyclerView; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | import opensource.zjt.rxnews.R; 19 | import opensource.zjt.rxnews.bean.ImageModel; 20 | import opensource.zjt.rxnews.presenter.ImagePresenter; 21 | import opensource.zjt.rxnews.presenter.ImagePresenterImpl; 22 | import opensource.zjt.rxnews.view.ImageViewInterface; 23 | 24 | /** 25 | */ 26 | public class ImageFragment extends Fragment implements ImageViewInterface, SwipeRefreshLayout.OnRefreshListener { 27 | 28 | private static final String TAG = "ImageFragment"; 29 | 30 | private SwipeRefreshLayout mSwipeRefreshWidget; 31 | private RecyclerView mRecyclerView; 32 | private LinearLayoutManager mLayoutManager; 33 | private ImageAdapter mAdapter; 34 | private List mData; 35 | private ImagePresenter mImagePresenter; 36 | 37 | @Override 38 | public void onCreate(@Nullable Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | mImagePresenter = new ImagePresenterImpl(this); 41 | } 42 | 43 | @Nullable 44 | @Override 45 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 46 | View view = inflater.inflate(R.layout.fragment_image, null); 47 | mSwipeRefreshWidget = (SwipeRefreshLayout) view.findViewById(R.id.swipe_refresh_widget); 48 | mSwipeRefreshWidget.setColorSchemeResources(R.color.colorPrimary, 49 | R.color.colorPrimaryDark, R.color.colorAccent, 50 | R.color.colorAccent); 51 | mSwipeRefreshWidget.setOnRefreshListener(this); 52 | 53 | mRecyclerView = (RecyclerView)view.findViewById(R.id.recycle_view); 54 | mRecyclerView.setHasFixedSize(true); 55 | 56 | mLayoutManager = new LinearLayoutManager(getActivity()); 57 | mRecyclerView.setLayoutManager(mLayoutManager); 58 | 59 | mRecyclerView.setItemAnimator(new DefaultItemAnimator()); 60 | mAdapter = new ImageAdapter(getActivity().getApplicationContext()); 61 | mRecyclerView.setAdapter(mAdapter); 62 | mRecyclerView.setOnScrollListener(mOnScrollListener); 63 | onRefresh(); 64 | return view; 65 | } 66 | 67 | private RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() { 68 | 69 | private int lastVisibleItem; 70 | 71 | @Override 72 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 73 | super.onScrolled(recyclerView, dx, dy); 74 | lastVisibleItem = mLayoutManager.findLastVisibleItemPosition(); 75 | } 76 | 77 | @Override 78 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 79 | super.onScrollStateChanged(recyclerView, newState); 80 | if (newState == RecyclerView.SCROLL_STATE_IDLE 81 | && lastVisibleItem + 1 == mAdapter.getItemCount() ) { 82 | //加载更多 83 | Snackbar.make(getActivity().findViewById(R.id.drawer_layout), getString(R.string.image_hit), Snackbar.LENGTH_SHORT).show(); 84 | } 85 | } 86 | }; 87 | 88 | @Override 89 | public void onRefresh() { 90 | if(mData != null) { 91 | mData.clear(); 92 | } 93 | mImagePresenter.loadImageList(); 94 | } 95 | 96 | @Override 97 | public void addImages(List list) { 98 | if(mData == null) { 99 | mData = new ArrayList(); 100 | } 101 | mData.addAll(list); 102 | mAdapter.setmDate(mData); 103 | } 104 | 105 | @Override 106 | public void showProgress() { 107 | mSwipeRefreshWidget.setRefreshing(true); 108 | } 109 | 110 | @Override 111 | public void hideProgress() { 112 | mSwipeRefreshWidget.setRefreshing(false); 113 | } 114 | 115 | @Override 116 | public void showLoadFailMsg() { 117 | View view = getActivity() == null ? mRecyclerView.getRootView() : getActivity().findViewById(R.id.drawer_layout); 118 | Snackbar.make(view, getString(R.string.load_fail), Snackbar.LENGTH_SHORT).show(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/ui/fragment/MyItemRecyclerViewAdapter.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.ui.fragment; 2 | 3 | import android.content.Context; 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.ImageView; 9 | import android.widget.TextView; 10 | 11 | import com.bumptech.glide.Glide; 12 | 13 | import opensource.zjt.rxnews.R; 14 | import opensource.zjt.rxnews.bean.NewsModel; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | */ 20 | public class MyItemRecyclerViewAdapter extends RecyclerView.Adapter { 21 | 22 | private static final int TYPE_ITEM = 0; 23 | private static final int TYPE_FOOTER = 1; 24 | 25 | private List mData; 26 | private boolean mShowFooter = true; 27 | private Context mContext; 28 | 29 | private OnItemClickListener mOnItemClickListener; 30 | 31 | public MyItemRecyclerViewAdapter(Context context) { 32 | this.mContext = context; 33 | } 34 | 35 | public void setmDate(List data) { 36 | this.mData = data; 37 | this.notifyDataSetChanged(); 38 | } 39 | 40 | @Override 41 | public int getItemViewType(int position) { 42 | // 最后一个item设置为footerView 43 | if(!mShowFooter) { 44 | return TYPE_ITEM; 45 | } 46 | if (position + 1 == getItemCount()) { 47 | return TYPE_FOOTER; 48 | } else { 49 | return TYPE_ITEM; 50 | } 51 | } 52 | 53 | @Override 54 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, 55 | int viewType) { 56 | if(viewType == TYPE_ITEM) { 57 | View v = LayoutInflater.from(parent.getContext()) 58 | .inflate(R.layout.fragment_item, parent, false); 59 | ItemViewHolder vh = new ItemViewHolder(v); 60 | return vh; 61 | } else { 62 | View view = LayoutInflater.from(parent.getContext()).inflate( 63 | R.layout.footer, null); 64 | view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 65 | ViewGroup.LayoutParams.WRAP_CONTENT)); 66 | return new FooterViewHolder(view); 67 | } 68 | } 69 | 70 | @Override 71 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 72 | if(holder instanceof ItemViewHolder) { 73 | 74 | NewsModel.NewslistEntity news = mData.get(position); 75 | if(news == null) { 76 | return; 77 | } 78 | ((ItemViewHolder) holder).mTitle.setText(news.getTitle()); 79 | ((ItemViewHolder) holder).mDesc.setText(news.getDescription()); 80 | Glide.with(mContext).load(news.getPicUrl()).error(R.drawable.ic_image_loadfail).placeholder(R.drawable.ic_image_loading) 81 | .into(((ItemViewHolder) holder).mNewsImg); 82 | } 83 | } 84 | 85 | @Override 86 | public int getItemCount() { 87 | int begin = mShowFooter?1:0; 88 | if(mData == null) { 89 | return begin; 90 | } 91 | return mData.size() + begin; 92 | } 93 | 94 | public NewsModel.NewslistEntity getItem(int position) { 95 | return mData == null ? null : mData.get(position); 96 | } 97 | 98 | public void isShowFooter(boolean showFooter) { 99 | this.mShowFooter = showFooter; 100 | } 101 | 102 | public boolean isShowFooter() { 103 | return this.mShowFooter; 104 | } 105 | 106 | public void setOnItemClickListener(OnItemClickListener onItemClickListener) { 107 | this.mOnItemClickListener = onItemClickListener; 108 | } 109 | 110 | public class FooterViewHolder extends RecyclerView.ViewHolder { 111 | 112 | public FooterViewHolder(View view) { 113 | super(view); 114 | } 115 | 116 | } 117 | 118 | public interface OnItemClickListener { 119 | public void onItemClick(View view, int position); 120 | } 121 | 122 | public class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 123 | 124 | public TextView mTitle; 125 | public TextView mDesc; 126 | public ImageView mNewsImg; 127 | 128 | public ItemViewHolder(View v) { 129 | super(v); 130 | mTitle = (TextView) v.findViewById(R.id.tvTitle); 131 | mDesc = (TextView) v.findViewById(R.id.tvDesc); 132 | mNewsImg = (ImageView) v.findViewById(R.id.ivNews); 133 | v.setOnClickListener(this); 134 | } 135 | 136 | @Override 137 | public void onClick(View view) { 138 | if(mOnItemClickListener != null) { 139 | mOnItemClickListener.onItemClick(view, this.getPosition()); 140 | } 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/ui/fragment/NewsFragment.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.ui.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.design.widget.TabLayout; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v4.app.FragmentManager; 8 | import android.support.v4.app.FragmentPagerAdapter; 9 | import android.support.v4.view.ViewPager; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | import butterknife.Bind; 18 | import butterknife.ButterKnife; 19 | import opensource.zjt.rxnews.R; 20 | import opensource.zjt.rxnews.base.AppService; 21 | import opensource.zjt.rxnews.base.BaseFragment; 22 | import opensource.zjt.rxnews.net.Constant; 23 | 24 | /** 25 | * Created by JianTao on 16/1/13. 26 | * Copyright © 2015 impetusconsulting. All rights reserved 27 | */ 28 | public class NewsFragment extends BaseFragment { 29 | @Bind(R.id.tab_layout) 30 | TabLayout tabLayout; 31 | @Bind(R.id.viewpager) 32 | ViewPager viewpager; 33 | 34 | @Override 35 | public void onCreate(@Nullable Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | } 38 | 39 | @Nullable 40 | @Override 41 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 42 | super.onCreateView(inflater, container, savedInstanceState); 43 | View view = inflater.inflate(R.layout.fragment_news, null); 44 | ButterKnife.bind(this, view); 45 | viewpager.setOffscreenPageLimit(3); 46 | viewpager.setCurrentItem(0); 47 | setViewPager(viewpager); 48 | tabLayout.setupWithViewPager(viewpager); 49 | return view; 50 | } 51 | 52 | private void setViewPager(ViewPager v) { 53 | MyPagerAdapter adapter = new MyPagerAdapter(getChildFragmentManager()); 54 | adapter.addFragment(NewsListFragment.newInstance(0),"科技"); 55 | adapter.addFragment(NewsListFragment.newInstance(1),"国际"); 56 | adapter.addFragment(NewsListFragment.newInstance(2),"社会"); 57 | adapter.addFragment(NewsListFragment.newInstance(3),"体育"); 58 | v.setAdapter(adapter); 59 | } 60 | 61 | public static class MyPagerAdapter extends FragmentPagerAdapter { 62 | private final List mFragments = new ArrayList<>(); 63 | private final List mFragmentTitles = new ArrayList<>(); 64 | 65 | public MyPagerAdapter(FragmentManager fm) { 66 | super(fm); 67 | } 68 | 69 | public void addFragment(Fragment fragment, String title) { 70 | mFragments.add(fragment); 71 | mFragmentTitles.add(title); 72 | } 73 | 74 | @Override 75 | public Fragment getItem(int position) { 76 | return mFragments.get(position); 77 | } 78 | 79 | @Override 80 | public int getCount() { 81 | return mFragments.size(); 82 | } 83 | 84 | @Override 85 | public CharSequence getPageTitle(int position) { 86 | return mFragmentTitles.get(position); 87 | } 88 | } 89 | 90 | @Override 91 | public void onDestroyView() { 92 | super.onDestroyView(); 93 | ButterKnife.unbind(this); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/ui/fragment/NewsListFragment.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.ui.fragment; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v4.app.ActivityCompat; 7 | import android.support.v4.app.ActivityOptionsCompat; 8 | import android.support.v4.app.Fragment; 9 | import android.support.v4.widget.SwipeRefreshLayout; 10 | import android.support.v7.widget.LinearLayoutManager; 11 | import android.support.v7.widget.RecyclerView; 12 | import android.view.LayoutInflater; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | 16 | import com.socks.library.KLog; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import butterknife.Bind; 22 | import butterknife.ButterKnife; 23 | import opensource.zjt.rxnews.R; 24 | import opensource.zjt.rxnews.base.AppService; 25 | import opensource.zjt.rxnews.bean.NewsModel; 26 | import opensource.zjt.rxnews.net.Constant; 27 | import opensource.zjt.rxnews.presenter.NewsPresenter; 28 | import opensource.zjt.rxnews.presenter.NewsPresenterImpl; 29 | import opensource.zjt.rxnews.ui.activity.NewsDetailActivity; 30 | import opensource.zjt.rxnews.view.NewsView; 31 | 32 | /** 33 | * A fragment representing a list of Items. 34 | *

35 | */ 36 | public class NewsListFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener, NewsView { 37 | 38 | private static final String ARG_COLUMN_COUNT = "column-count"; 39 | private static final String TAG = NewsListFragment.class.getName(); 40 | @Bind(R.id.recyclerView_list) 41 | RecyclerView recyclerView; 42 | @Bind(R.id.swipe_refresh_widget) 43 | SwipeRefreshLayout mSwipeRefreshWidget; 44 | private int mColumnCount = 1; 45 | private LinearLayoutManager mLayoutManager; 46 | private int pageIndex = 1; 47 | private List mData; 48 | private NewsPresenter mNewsPresenter; 49 | 50 | /** 51 | * Mandatory empty constructor for the fragment manager to instantiate the 52 | * fragment (e.g. upon screen orientation changes). 53 | */ 54 | public NewsListFragment() { 55 | } 56 | 57 | // TODO: Customize parameter initialization 58 | @SuppressWarnings("unused") 59 | public static NewsListFragment newInstance(int columnCount) { 60 | NewsListFragment fragment = new NewsListFragment(); 61 | Bundle args = new Bundle(); 62 | args.putInt(ARG_COLUMN_COUNT, columnCount); 63 | fragment.setArguments(args); 64 | return fragment; 65 | } 66 | 67 | @Override 68 | public void onCreate(Bundle savedInstanceState) { 69 | super.onCreate(savedInstanceState); 70 | 71 | if (getArguments() != null) { 72 | mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT); 73 | } 74 | AppService.getInstance().initNews(getActivity().getTaskId(), getID(mColumnCount)); 75 | } 76 | 77 | @Override 78 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 79 | Bundle savedInstanceState) { 80 | View view = inflater.inflate(R.layout.fragment_item_list, container, false); 81 | ButterKnife.bind(this, view); 82 | mSwipeRefreshWidget.setColorSchemeResources(R.color.colorAccent, 83 | R.color.colorAccent, R.color.colorPrimaryDark, 84 | R.color.colorAccent); 85 | mSwipeRefreshWidget.setOnRefreshListener(this); 86 | mLayoutManager = new LinearLayoutManager(getActivity()); 87 | 88 | recyclerView.setLayoutManager(mLayoutManager); 89 | recyclerView.setHasFixedSize(true); 90 | mAdapter = new MyItemRecyclerViewAdapter(getContext().getApplicationContext()); 91 | mAdapter.setOnItemClickListener(mOnItemClickListener); 92 | recyclerView.setAdapter(mAdapter); 93 | recyclerView.setOnScrollListener(mOnScrollListener); 94 | mNewsPresenter = new NewsPresenterImpl(this); 95 | onRefresh(); 96 | return view; 97 | } 98 | 99 | private MyItemRecyclerViewAdapter mAdapter; 100 | private RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() { 101 | 102 | private int lastVisibleItem; 103 | 104 | @Override 105 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 106 | super.onScrolled(recyclerView, dx, dy); 107 | lastVisibleItem = mLayoutManager.findLastVisibleItemPosition(); 108 | } 109 | 110 | @Override 111 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 112 | super.onScrollStateChanged(recyclerView, newState); 113 | if (newState == RecyclerView.SCROLL_STATE_IDLE 114 | && lastVisibleItem + 1 == mAdapter.getItemCount() 115 | && mAdapter.isShowFooter()) { 116 | //加载更多 117 | KLog.d(TAG, "loading more data"); 118 | mNewsPresenter.loadNews(mColumnCount, pageIndex++); 119 | } 120 | } 121 | }; 122 | private MyItemRecyclerViewAdapter.OnItemClickListener mOnItemClickListener = new MyItemRecyclerViewAdapter.OnItemClickListener() { 123 | @Override 124 | public void onItemClick(View view, int position) { 125 | NewsModel.NewslistEntity news = mAdapter.getItem(position); 126 | Intent intent = new Intent(getActivity(), NewsDetailActivity.class); 127 | intent.putExtra(Constant.NEWSDETAIL, news); 128 | View transitionView = view.findViewById(R.id.ivNews); 129 | ActivityOptionsCompat options = 130 | ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(), 131 | transitionView, getString(R.string.transition_news_img)); 132 | 133 | ActivityCompat.startActivity(getActivity(), intent, options.toBundle()); 134 | } 135 | }; 136 | 137 | 138 | @Override 139 | public void onDetach() { 140 | super.onDetach(); 141 | } 142 | 143 | @Override 144 | public void onDestroy() { 145 | super.onDestroy(); 146 | // ButterKnife.unbind(this); 147 | } 148 | 149 | @Override 150 | public void onRefresh() { 151 | pageIndex = 1; 152 | if (mData != null) { 153 | mData.clear(); 154 | } 155 | mNewsPresenter.loadNews(mColumnCount, pageIndex); 156 | } 157 | 158 | @Override 159 | public void addNew(List list) { 160 | mAdapter.isShowFooter(true); 161 | if (mData == null) { 162 | mData = new ArrayList<>(); 163 | } 164 | mData.addAll(list); 165 | if (pageIndex == 1) { 166 | mAdapter.setmDate(mData); 167 | } else { 168 | if (list == null || list.size() == 0) { 169 | mAdapter.isShowFooter(false); 170 | } 171 | mAdapter.notifyDataSetChanged(); 172 | } 173 | pageIndex += Constant.PAZE_SIZE; 174 | } 175 | 176 | @Override 177 | public void showProgress() { 178 | if (mSwipeRefreshWidget != null) 179 | mSwipeRefreshWidget.setRefreshing(true); 180 | } 181 | 182 | @Override 183 | public void hideProgress() { 184 | if (mSwipeRefreshWidget != null) 185 | mSwipeRefreshWidget.setRefreshing(false); 186 | } 187 | 188 | @Override 189 | public void showLoadFail() { 190 | if (pageIndex == 1) { 191 | mAdapter.isShowFooter(false); 192 | mAdapter.notifyDataSetChanged(); 193 | } 194 | View view = getActivity() == null ? recyclerView.getRootView() : getActivity().findViewById(R.id.drawer_layout); 195 | Snackbar.make(view, getString(R.string.load_fail), Snackbar.LENGTH_SHORT).show(); 196 | } 197 | 198 | private String getID(int type) { 199 | String id; 200 | switch (type) { 201 | case 0: 202 | id = Constant.NEWSTYPE_KEJI; 203 | break; 204 | case 1: 205 | id = Constant.NEWSTYPE_GUOJI; 206 | break; 207 | case 2: 208 | id = Constant.NEWSTYPE_SHEHUI; 209 | break; 210 | case 3: 211 | id = Constant.NEWSTYPE_TIYU; 212 | break; 213 | default: 214 | id = Constant.NEWSTYPE_KEJI; 215 | break; 216 | } 217 | return id; 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/utils/AppUtils.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.utils; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageManager; 5 | import android.content.res.Resources; 6 | import android.graphics.Color; 7 | import android.net.ConnectivityManager; 8 | import android.net.NetworkInfo; 9 | import android.support.design.widget.Snackbar; 10 | import android.view.View; 11 | import android.widget.TextView; 12 | 13 | import opensource.zjt.rxnews.R; 14 | import opensource.zjt.rxnews.base.BaseApplication; 15 | 16 | 17 | /** 18 | */ 19 | public class AppUtils { 20 | 21 | public static String getVersionName(Context context) { 22 | String versionName = null; 23 | try { 24 | versionName = context.getApplicationContext().getPackageManager() 25 | .getPackageInfo(context.getApplicationContext().getPackageName(), 0).versionName; 26 | } catch (PackageManager.NameNotFoundException e) { 27 | e.printStackTrace(); 28 | } 29 | return versionName; 30 | } 31 | 32 | 33 | public static void showSnackBar(View view, int id) { 34 | Resources resources = BaseApplication.getmContext().getResources(); 35 | Snackbar sb = Snackbar.make(view, resources.getString(id), Snackbar.LENGTH_SHORT); 36 | setSnackbarMessageTextColor(sb); 37 | sb.getView().setBackgroundColor(resources.getColor(R.color.main_bg)); 38 | sb.show(); 39 | } 40 | 41 | public static void setSnackbarMessageTextColor(Snackbar snackbar) { 42 | View view = snackbar.getView(); 43 | ((TextView) view.findViewById(R.id.snackbar_text)).setTextColor(Color.parseColor("#448AFF")); 44 | } 45 | 46 | /** 47 | * 判断网络是否可用 48 | * 49 | * @param context Context对象 50 | */ 51 | public static Boolean isNetworkReachable(Context context) { 52 | ConnectivityManager cm = (ConnectivityManager) context 53 | .getSystemService(Context.CONNECTIVITY_SERVICE); 54 | NetworkInfo current = cm.getActiveNetworkInfo(); 55 | if (current == null) { 56 | return false; 57 | } 58 | return (current.isAvailable()); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/view/ImageViewInterface.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.view; 2 | 3 | import java.util.List; 4 | 5 | import opensource.zjt.rxnews.bean.ImageModel; 6 | 7 | public interface ImageViewInterface { 8 | void addImages(List list); 9 | 10 | void showProgress(); 11 | 12 | void hideProgress(); 13 | 14 | void showLoadFailMsg(); 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/view/NewsDetailView.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.view; 2 | 3 | /** 4 | * Created by JianTao on 16/1/21. 5 | * Copyright © 2015 impetusconsulting. All rights reserved 6 | */ 7 | public interface NewsDetailView { 8 | void showNewsDetailContent(String detailurl); 9 | 10 | void showProgress(); 11 | 12 | void hideProgress(); 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/opensource/zjt/rxnews/view/NewsView.java: -------------------------------------------------------------------------------- 1 | package opensource.zjt.rxnews.view; 2 | 3 | import java.util.List; 4 | 5 | import opensource.zjt.rxnews.bean.NewsModel; 6 | 7 | /** 8 | * Created by JianTao on 16/1/21. 9 | * Copyright © 2015 impetusconsulting. All rights reserved 10 | */ 11 | public interface NewsView { 12 | void addNew(List list); 13 | 14 | void showProgress(); 15 | 16 | void hideProgress(); 17 | 18 | void showLoadFail(); 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_camera.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_gallery.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_manage.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_send.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_share.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_slideshow.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_image_loadfail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiantao88/RxNews/0fb3bfe2219caac704543a4c1a62803362ce2dd0/app/src/main/res/drawable-xxhdpi/ic_image_loadfail.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_image_loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiantao88/RxNews/0fb3bfe2219caac704543a4c1a62803362ce2dd0/app/src/main/res/drawable-xxhdpi/ic_image_loading.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 16 | 17 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_news_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 23 | 24 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/res/layout/app_bar_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 21 | 22 | 23 | 24 | 32 | 33 | 34 | 35 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/footer.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 16 | 17 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | 18 | 23 | 24 | 29 | 30 | 38 | 39 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_item_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_news.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 17 | 18 | 19 | 20 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 25 | 26 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/nav_header_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 20 | 21 | 27 | 28 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/menu/activity_main_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 9 | 13 | 17 | 21 | 22 | 23 | 24 | 25 | 29 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiantao88/RxNews/0fb3bfe2219caac704543a4c1a62803362ce2dd0/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiantao88/RxNews/0fb3bfe2219caac704543a4c1a62803362ce2dd0/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiantao88/RxNews/0fb3bfe2219caac704543a4c1a62803362ce2dd0/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiantao88/RxNews/0fb3bfe2219caac704543a4c1a62803362ce2dd0/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiantao88/RxNews/0fb3bfe2219caac704543a4c1a62803362ce2dd0/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | #212121 8 | #727272 9 | #eceff1 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 160dp 5 | 6 | 16dp 7 | 16dp 8 | 16dp 9 | 16dp 10 | 16sp 11 | 12sp 12 | 5dp 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/values/drawables.xml: -------------------------------------------------------------------------------- 1 | 2 | @android:drawable/ic_menu_camera 3 | @android:drawable/ic_menu_gallery 4 | @android:drawable/ic_menu_slideshow 5 | @android:drawable/ic_menu_manage 6 | @android:drawable/ic_menu_share 7 | @android:drawable/ic_menu_send 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | RxNews 3 | 4 | Open navigation drawer 5 | Close navigation drawer 6 | 7 | Settings 8 | transition_news_img 9 | 加载失败 10 | 11 | 12 | Hello blank fragment 13 | 加载更多 14 | 暂未实现 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 |