TouTiao开源项目 分析笔记5

Posted Jason_Jan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TouTiao开源项目 分析笔记5相关的知识,希望对你有一定的参考价值。

1.深入理解RxJava

1.1.基本上现在的APP都会有请求网络,然后处理回调的业务吧。

  如果请求的数据很多,业务越来越复杂,怎么处理呢?

  这里我用到了RxJava来帮我处理业务。

  RxJava主要复杂事件的通知和订阅。这个挺起来没有什么概念。

  其实说白了,RxJava就是优雅地处理函数回调。

 

1.2.推荐参考文章:我们为什么要用rxjava?

  这篇文章以一个案例的方式,详细解释了rxjava的功能。

  下面我来深入分析一下。

 

1.3.以通常思维模式来处理这个案例。

  

  这个比较好理解,但是这种方式不是异步请求。现在网络请求基本都要异步线程调用。

 

1.4.那么修改一下实现方式。

  

 

1.5.有匿名类,然后消除

  

  这里将Callback<T>封装起来为一个Task<T>任务了。

 

1.6.处理逻辑层

  

 

1.7.定义一个抽象类AbstractTask<T> 来实现Task<T>

  

 

1.8.最终业务层

  

 


2.自定义RxBus

2.1.参考文章:Android RxJava实现RxBus。

  源代码:

package com.meiji.toutiao;

import android.support.annotation.NonNull;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import io.reactivex.Observable;
import io.reactivex.subjects.PublishSubject;
import io.reactivex.subjects.Subject;

/**
 * https://juejin.im/entry/58ff2e26a0bb9f0065d2c5f2
 */


public class RxBus {

    private ConcurrentHashMap<Object, List<Subject>> subjectMapper =
            new ConcurrentHashMap<>();

    private RxBus() {

    }

    private static class Holder {
        private static RxBus instance = new RxBus();
    }

    @NonNull
    public static RxBus getInstance() {
        return Holder.instance;
    }

    @NonNull
    public <T> Observable<T> register(@NonNull Class<T> clz) {
        return register(clz.getName());
    }

    @NonNull
    public <T> Observable<T> register(@NonNull Object tag) {
        List<Subject> subjectList = subjectMapper.get(tag);
        if (null == subjectList) {
            subjectList = new ArrayList<>();
            subjectMapper.put(tag, subjectList);
        }

        Subject<T> subject = PublishSubject.create();
        subjectList.add(subject);

        //System.out.println("注册到rxbus");
        return subject;
    }

    public <T> void unregister(@NonNull Class<T> clz, @NonNull Observable observable) {
        unregister(clz.getName(), observable);
    }

    public void unregister(@NonNull Object tag, @NonNull Observable observable) {
        List<Subject> subjects = subjectMapper.get(tag);
        if (null != subjects) {
            subjects.remove(observable);
            if (subjects.isEmpty()) {
                subjectMapper.remove(tag);
                //System.out.println("从rxbus取消注册");
            }
        }
    }

    public void post(@NonNull Object content) {
        post(content.getClass().getName(), content);
    }

    public void post(@NonNull Object tag, @NonNull Object content) {
        List<Subject> subjects = subjectMapper.get(tag);
        if (!subjects.isEmpty()) {
            for (Subject subject : subjects) {
                subject.onNext(content);
            }
        }
    }

}
View Code

 

2.2.定义一个ConcurrentHashMap。

  顾名思义,类似于HashMap,用来临时存储数据的。而且处理了一些多线程安全之类的东西。

private ConcurrentHashMap<Object, List<Subject>> subjectMapper = 
            new ConcurrentHashMap<>();

 

2.3.然后是新建一个实例

    private RxBus() {}

    private static class Holder {
        private static RxBus instance = new RxBus();
    }

    @NonNull
    public static RxBus getInstance() {
        return Holder.instance;
    }

 

2.4. 注册的两个方法

@NonNull
    public <T> Observable<T> register(@NonNull Class<T> clz) {
        return register(clz.getName());
    }

    @NonNull
    public <T> Observable<T> register(@NonNull Object tag) {
        List<Subject> subjectList = subjectMapper.get(tag);
        if (null == subjectList) {
            subjectList = new ArrayList<>();
            subjectMapper.put(tag, subjectList);
        }

        Subject<T> subject = PublishSubject.create();
        subjectList.add(subject);

        //System.out.println("注册到rxbus");
        return subject;
    }

  传入一个Class<T>参数

  或传入一个Object 参数

  返回一个Observable<T>类型数据

  这里返回一个Subject<T>类型数据

 

2.5.反注册的两个方法 

 public <T> void unregister(@NonNull Class<T> clz, @NonNull Observable observable) {
        unregister(clz.getName(), observable);
    }

    public void unregister(@NonNull Object tag, @NonNull Observable observable) {
        List<Subject> subjects = subjectMapper.get(tag);
        if (null != subjects) {
            subjects.remove(observable);
            if (subjects.isEmpty()) {
                subjectMapper.remove(tag);
                //System.out.println("从rxbus取消注册");
            }
        }
    }

  传入两个参数:Class<T> clz,Observable observable

  或传入两个参数:Object tag,Observable obervable

  调用subjectMapper的remove(tag)方法来取消注册。

 

2.6.两个post方法

    public void post(@NonNull Object content) {
        post(content.getClass().getName(), content);
    }

    public void post(@NonNull Object tag, @NonNull Object content) {
        List<Subject> subjects = subjectMapper.get(tag);
        if (!subjects.isEmpty()) {
            for (Subject subject : subjects) {
                subject.onNext(content);
            }
        }
    }

  传入一个参数Object content

  或传入两个参数:Object tag,Object Content

  调用subject.onNext(content)来post。

  不返回数据。


3.DatabaseHelper帮助器

3.1.源代码

package com.jasonjan.headnews.database.helper;

import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.jasonjan.headnews.database.table.MediaChannelTable;
import com.jasonjan.headnews.database.table.NewsChannelTable;
import com.jasonjan.headnews.database.table.SearchHistoryTable;
import com.jasonjan.headnews.global.InitApp;

/**
 * Created by JasonJan on 2017/12/4.
 */

public class DatabaseHelper extends SQLiteOpenHelper{

    private static final String DB_NAME = "Toutiao";
    private static final int DB_VERSION = 5;
    private static final String CLEAR_TABLE_DATA = "delete from ";
    private static final String DROP_TABLE = "drop table if exists ";
    private static DatabaseHelper instance = null;
    private static SQLiteDatabase db = null;

    private DatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    private static synchronized DatabaseHelper getInstance() {
        if (instance == null) {
            instance = new DatabaseHelper(InitApp.AppContext, DB_NAME, null, DB_VERSION);
        }
        return instance;
    }

    public static synchronized SQLiteDatabase getDatabase() {
        if (db == null) {
            db = getInstance().getWritableDatabase();
        }
        return db;
    }

    public static synchronized void closeDatabase() {
        if (db != null) {
            db.close();
        }
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(NewsChannelTable.CREATE_TABLE);
        db.execSQL(MediaChannelTable.CREATE_TABLE);
        db.execSQL(SearchHistoryTable.CREATE_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        switch (oldVersion) {
            case 1:
                db.execSQL(MediaChannelTable.CREATE_TABLE);
                break;
            case 2:
                db.execSQL(CLEAR_TABLE_DATA + NewsChannelTable.TABLENAME);
                break;
            case 3:
                ContentValues values = new ContentValues();
                values.put(NewsChannelTable.ID, "");
                values.put(NewsChannelTable.NAME, "推荐");
                values.put(NewsChannelTable.IS_ENABLE, 0);
                values.put(NewsChannelTable.POSITION, 46);
                db.insert(NewsChannelTable.TABLENAME, null, values);
                break;
            case 4:
                db.execSQL(SearchHistoryTable.CREATE_TABLE);
                break;
        }
    }
}

  synchronized关键字:加了同步锁,保证线程同步。


4.三张原始表

4.1.NewsChannelTable

public class NewsChannelTable {
    /**
     * 新闻频道信息表
     */
    public static final String TABLENAME = "NewsChannelTable";

    /**
     * 字段部分
     */
    public static final String ID = "id";
    public static final String NAME = "name";
    public static final String IS_ENABLE = "isEnable";
    public static final String POSITION = "position";

    /**
     * 字段ID 数据库操作建立字段对应关系 从0开始
     */
    public static final int ID_ID = 0;
    public static final int ID_NAME = 1;
    public static final int ID_ISENABLE = 2;
    public static final int ID_POSITION = 3;

    /**
     * 创建表
     */
    public static final String CREATE_TABLE = "create table if not exists " + TABLENAME + "(" +
            ID + " text primary key, " +
            NAME + " text, " +
            IS_ENABLE + " text default \'1\', " +
            POSITION + " text) ";
}
View Code

 

4.2.MediaChannelTable

public class MediaChannelTable {
    /**
     * 头条号信息表
     */
    public static final String TABLENAME = "MediaChannelTable";

    /**
     * 字段部分
     */
    public static final String ID = "id";
    public static final String NAME = "name";
    public static final String AVATAR = "avatar";
    public static final String TYPE = "type";
    public static final String FOLLOWCOUNT = "followCount";
    public static final String DESCTEXT = "descText";
    public static final String URL = "url";

    /**
     * 字段ID 数据库操作建立字段对应关系 从0开始
     */
    public static final int ID_ID = 0;
    public static final int ID_NAME = 1;
    public static final int ID_AVATAR = 2;
    public static final int ID_TYPE = 3;
    public static final int ID_FOLLOWCOUNT = 4;
    public static final int ID_DESCTEXT = 5;
    public static final int ID_URL = 6;

    /**
     * 创建表
     */
    public static final String CREATE_TABLE = "create table if not exists " + TABLENAME + "(" +
            ID + " text primary key, " +
            NAME + " text, " +
            AVATAR + " text, " +
            TYPE + " text, " +
            FOLLOWCOUNT + " text, " +
            DESCTEXT + " text, " +
            URL + " text) ";
}
View Code

 

4.3.SearchHistoryTable

public class SearchHistoryTable {
    /**
     * 浏览记录表
     */
    public static final String TABLENAME = "SearchHistoryTable";

    /**
     * 字段部分
     */
    public static final String ID = "id";
    public static final String KEYWORD = "keyWord";
    public static final String TIME = "time";

    /**
     * 字段ID 数据库操作建立字段对应关系 从0开始
     */
    public static final int ID_ID = 0;
    public static final int ID_KEYWORD = 1;
    public static final int ID_TIME = 2;

    /**
     * 创建表
     */
    public static final String CREATE_TABLE = "create table if not exists " + TABLENAME + "(" +
            ID + " text auto_increment, " +
            KEYWORD + " text primary key, " +
            TIME + " text) ";
}
View Code

 

  这三张表示基础表。和数据缓存有关系。   



以上是关于TouTiao开源项目 分析笔记5的主要内容,如果未能解决你的问题,请参考以下文章

TouTiao开源项目 分析笔记4

TouTiao开源项目 分析笔记7

TouTiao开源项目 分析笔记19 问答内容

TouTiao开源项目 分析笔记14 段子评论

TouTiao开源项目 分析笔记9 实现一个问答主页面

TouTiao开源项目 分析笔记13 最后一个订阅号的实现主页面