public class RestClient {
    //http://localhost:63342/examples/EManual
//	public static final String BASE_URL = "http://192.168.0.105:8080"; // main 
//	public static final String BASE_URL ="http://192.168.199.221:8081";
    //http://jayin.github.io/EManual
    public static final String BASE_URL = "http://emanual.github.io";
    public static final String URL_Preview = BASE_URL + "/assets/preview.html";
    public static final String URL_NewsFeeds = BASE_URL + "/md-newsfeeds/dist/%s";
    public static final String URL_Java = BASE_URL + "/java";
    public static final String URL_FEEDS = " http://emanualresource.github.io";
    private static int HTTP_Timeout = 12 * 1000;
    public static Context context;

    private static AsyncHttpClient client;

    public static AsyncHttpClient getHttpClient() {
        if (client == null) {
            client = new AsyncHttpClient();
        }
        return client;
    }

    /**
     * 初始化:如果需要调用登录验证记录session的函数前，必须调用这个方法，否则请求失败
     *
     * @param context Activity or Application context
     */
    public static void init(Context context) {
        RestClient.context = context;
        client = getHttpClient();
    }

    /**
     * get method
     *
     * @param url             相对的url
     * @param params
     * @param responseHandler
     */
    public static void get(String url, RequestParams params,
                           AsyncHttpResponseHandler responseHandler) {
        get(BASE_URL, url, params, responseHandler);
    }

    public static void get(String baseUrl, String url, RequestParams params,
                           AsyncHttpResponseHandler responseHandler) {
        initClient();
        client.get(baseUrl + url, params, responseHandler);
    }

    /**
     * post method
     *
     * @param url
     * @param params
     * @param responseHandler
     */
    public static void post(String url, RequestParams params,
                            AsyncHttpResponseHandler responseHandler) {
        initClient();
        client.post(getAbsoluteUrl(url), params, responseHandler);

    }

    /**
     * 请求前初始化<br>
     * 必须在请求之前初始化，不然cookie失效<br>
     * context不为空时带着cookie去访问<br>
     */
    private static void initClient() {
        if (context != null)
            client.setCookieStore(new PersistentCookieStore(context));
        client.setTimeout(HTTP_Timeout);
        client.setEnableRedirects(true);
    }

    /**
     * 获得绝对url
     *
     * @param relativeUrl
     * @return
     */
    private static String getAbsoluteUrl(String relativeUrl) {
        return BASE_URL + relativeUrl;
    }
} public class FeedsItemEntity extends BaseEntity implements Serializable{
    private String name;
    private String name_cn;
    private String md5;
    private String icon_url;
    private String url;
    private String author;
    private String homepage;

    /**
     * 获取book的下载url
     * NOTE:
     *  在url上加上`?v=xxxx`
     * @return
     */
    public String getDownloadUrl(){
        return String.format("%s?v=%s", getUrl(), getMd5());
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getHomepage() {
        return homepage;
    }

    public void setHomepage(String homepage) {
        this.homepage = homepage;
    }

    public String getIcon_url() {
        return icon_url;
    }

    public void setIcon_url(String icon_url) {
        this.icon_url = icon_url;
    }

    public String getMd5() {
        return md5;
    }

    public void setMd5(String md5) {
        this.md5 = md5;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName_cn() {
        return name_cn;
    }

    public void setName_cn(String name_cn) {
        this.name_cn = name_cn;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    @Override public String toString() {
        return "FeedsItemEntity{" +
                "author='" + author + '\'' +
                ", name='" + name + '\'' +
                ", name_cn='" + name_cn + '\'' +
                ", md5='" + md5 + '\'' +
                ", icon_url='" + icon_url + '\'' +
                ", url='" + url + '\'' +
                ", homepage='" + homepage + '\'' +
                '}';
    }
} public class BookDownloadEndEvent extends BaseEvent{
    private File file;
    private FeedsItemEntity feedsItemEntity;

    public BookDownloadEndEvent(File file, FeedsItemEntity feedsItemEntity){
        this.file = file;
        this.feedsItemEntity = feedsItemEntity;
    }

    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
    }

    public FeedsItemEntity getFeedsItemEntity() {
        return feedsItemEntity;
    }

    public void setFeedsItemEntity(FeedsItemEntity feedsItemEntity) {
        this.feedsItemEntity = feedsItemEntity;
    }
} public class BookDownloadFaildEvent extends BaseEvent {

    private int statusCode;
    private Header[] headers;
    private Throwable throwable;

    public BookDownloadFaildEvent(int statusCode, Header[] headers, Throwable throwable) {
        this.statusCode = statusCode;
        this.headers = headers;
        this.throwable = throwable;
    }

    public Header[] getHeaders() {
        return headers;
    }

    public int getStatusCode() {
        return statusCode;
    }

    public Throwable getThrowable() {
        return throwable;
    }
} public class BookDownloadProgressEvent extends BaseEvent {

    private long bytesWritten;
    private long totalSize;

    /**
     * @param bytesWritten 已下载
     * @param totalSize    总大小
     */
    public BookDownloadProgressEvent(long bytesWritten, long totalSize) {
        this.bytesWritten = bytesWritten;
        this.totalSize = totalSize;
    }

    public long getBytesWritten() {
        return bytesWritten;
    }

    public void setBytesWritten(long bytesWritten) {
        this.bytesWritten = bytesWritten;
    }

    public long getTotalSize() {
        return totalSize;
    }

    public void setTotalSize(long totalSize) {
        this.totalSize = totalSize;
    }
} public class BookDownloadStartEvent extends BaseEvent {

} public class InterviewDownloadEndEvent extends BaseEvent {
    private File file;
    private FeedsItemEntity feedsItemEntity;

    public InterviewDownloadEndEvent(File file, FeedsItemEntity feedsItemEntity){
        this.file = file;
        this.feedsItemEntity = feedsItemEntity;
    }

    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
    }

    public FeedsItemEntity getFeedsItemEntity() {
        return feedsItemEntity;
    }

    public void setFeedsItemEntity(FeedsItemEntity feedsItemEntity) {
        this.feedsItemEntity = feedsItemEntity;
    }
} public class InterviewDownloadFaildEvent extends BaseEvent {
    private int statusCode;
    private Header[] headers;
    private Throwable throwable;

    public InterviewDownloadFaildEvent(int statusCode, Header[] headers, Throwable throwable) {
        this.statusCode = statusCode;
        this.headers = headers;
        this.throwable = throwable;
    }

    public Header[] getHeaders() {
        return headers;
    }

    public int getStatusCode() {
        return statusCode;
    }

    public Throwable getThrowable() {
        return throwable;
    }
} public class InterviewDownloadProgressEvent extends BaseEvent {
    private long bytesWritten;
    private long totalSize;

    /**
     * @param bytesWritten 已下载
     * @param totalSize    总大小
     */
    public InterviewDownloadProgressEvent(long bytesWritten, long totalSize) {
        this.bytesWritten = bytesWritten;
        this.totalSize = totalSize;
    }

    public long getBytesWritten() {
        return bytesWritten;
    }

    public void setBytesWritten(long bytesWritten) {
        this.bytesWritten = bytesWritten;
    }

    public long getTotalSize() {
        return totalSize;
    }

    public void setTotalSize(long totalSize) {
        this.totalSize = totalSize;
    }
} public class InterviewDownloadStartEvent extends BaseEvent {
} public class AppPath {
    /**
     * 获取应用files/ 目录：/data/data/<App Name>/files
     * @param context
     * @return
     */
    public static String getAppFilesPath(Context context){
        return context.getFilesDir().getAbsolutePath();
    }
    /**
     * 获取文档下载目录,/data/data/<App Name>/files/download
     * @param context
     * @return
     */
    public static String getDownloadPath(Context context){
        return getAppFilesPath(context) + File.separator + "download";
    }
    /**
     * 获取文档目录,/data/data/<App Name>/files/books
     * @param context
     * @return
     */
    public static String getBooksPath(Context context){
        return getAppFilesPath(context) + File.separator + "books";
    }

    /**
     * 获取文档目录,/data/data/<App Name>/files/interviews
     * @param context
     * @return
     */
    public static String getInterviewsPath(Context context){
        return getAppFilesPath(context) + File.separator + "interviews";
    }

    //========Book

    /**
     * 获取教程的根目录/data/data/<App Name>/files/books/<bookName>
     * @param context
     * @param bookName 书名
     * @return
     */
    public static String getBookRootPath(Context context, String bookName){
        return getBooksPath(context) + File.separator + bookName;
    }

    /**
     * 获取教程的book目录：/data/data/<App Name>/files/books/<bookName>/book
     * @param context
     * @param bookname
     * @return
     */
    public static String getBookPath(Context context, String bookname) {
        return getBookRootPath(context, bookname) + File.separator + "book";
    }
    /**
     * 获取教程的book.json /data/data/<App Name>/files/books/<bookName>/book/book.json
     * @param context
     * @return
     */
    public static String getBookJSONFilePath(Context context, String bookName){
        return getBookPath(context, bookName) + File.separator + "book.json";
    }

    //=========== Interview

    /**
     * 获取Interview的根目录/data/data/<App Name>/files/interviews/<interviewName>
     * @param context
     * @param interviewName
     * @return
     */
    public static String getInterviewRootPath(Context context, String interviewName){
        return getInterviewsPath(context) + File.separator + interviewName;
    }

    /**
     * 获取Interview的Interview目录：/data/data/<App Name>/files/books/<bookName>/interview
     * @param context
     * @param interviewName
     * @return
     */
    public static String getInterviewPath(Context context, String interviewName) {
        return getInterviewRootPath(context, interviewName) + File.separator + "interview";
    }

    /**
     * 获取Interview的questions目录/data/data/<App Name>/files/interviews/<interviewName>/interview/questions
     * @param context
     * @param interviewName
     * @return
     */
    public static String getInterviewQuestionsRootPath(Context context, String interviewName){
        return getInterviewPath(context, interviewName) + File.separator + "questions";
    }

    /**
     * 获取教程的interview.json /data/data/<App Name>/files/books/<bookName>/interview/interview.json
     * @param context
     * @param interviewName
     * @return
     */
    public static String getInterviewJSONFilePath(Context context, String interviewName){
        return getInterviewPath(context, interviewName) + File.separator + "interview.json";
    }

    /**
     * 获取教程的入口文件(index.html)
     * /data/data/<App Name>/files/books/<bookName>/book/index.html
     * @param context
     * @param bookName 书名
     * @return
     */
    public static String getBookIndexURL(Context context, String bookName){
        return "file:///"+getBookPath(context, bookName) + File.separator + "index.html";
    }
}
import android.content.Context;
import android.net.Uri;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.loopj.android.http.FileAsyncHttpResponseHandler;
import java.io.File;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import cz.msebera.android.httpclient.Header;
import de.greenrobot.event.EventBus;
import io.github.emanual.app.R;
import io.github.emanual.app.api.RestClient;
import io.github.emanual.app.entity.FeedsItemEntity;
import io.github.emanual.app.ui.event.BookDownloadEndEvent;
import io.github.emanual.app.ui.event.BookDownloadFaildEvent;
import io.github.emanual.app.ui.event.BookDownloadProgressEvent;
import io.github.emanual.app.ui.event.BookDownloadStartEvent;
import io.github.emanual.app.ui.event.InterviewDownloadEndEvent;
import io.github.emanual.app.ui.event.InterviewDownloadFaildEvent;
import io.github.emanual.app.ui.event.InterviewDownloadProgressEvent;
import io.github.emanual.app.ui.event.InterviewDownloadStartEvent;
import io.github.emanual.app.utils.AppPath;
import timber.log.Timber;
package io.github.emanual.app.ui.adapter;





/**
 * Author: jayin
 * Date: 1/19/16
 */
public class FeedsListAdapter extends RecyclerView.Adapter<FeedsListAdapter.ViewHolder> {
    Context context;
    List<FeedsItemEntity> data;