10分鐘開(kāi)發(fā)網(wǎng)易新聞首頁(yè)的框架

序言

最近快半個(gè)月沒(méi)寫博客畔规,不是偷懶而是在整理一些思路盗冷,最近的項(xiàng)目中開(kāi)始嘗試使用新框架丐枉,也一直在改進(jìn)中蕴潦,最后覺(jué)得差不多了準(zhǔn)備開(kāi)源出來(lái)蓬豁。10分鐘開(kāi)發(fā)網(wǎng)易新聞首頁(yè)有點(diǎn)夸大其詞,但是在我的Demo中修改一下樣式基本就能滿足大多數(shù)新聞客戶端的需求了熙掺,其他的APP更不在話下。

效果

1.這是長(zhǎng)截屏,主要展示的樣式的復(fù)雜度悠鞍,和網(wǎng)易新聞首頁(yè)相比差不了多少。

這里寫圖片描述

2.這是動(dòng)態(tài)效果模燥,集成了咖祭,下拉刷新,上拉加載更多蔫骂,錯(cuò)誤重試么翰,當(dāng)然這些界面都是可以自定義的。

這里寫圖片描述
這里寫圖片描述

3.直接使用布局文件實(shí)現(xiàn)自定義辽旋,最終框架將自動(dòng)替換與添加相應(yīng)的部分浩嫌。

布局文件如下

這里寫圖片描述

代碼就只有這么多

這里寫圖片描述

效果很爽

這里寫圖片描述
這里寫圖片描述

使用

1.配置

1.使用起來(lái)很簡(jiǎn)單,先看代碼

這是BaseFragment繼承自SmartListFragment戴已,而SmartListFragment就是我框架中的類了固该,這里面返回了當(dāng)前應(yīng)用的分頁(yè)策略,方便統(tǒng)一控制糖儡。

這里寫圖片描述

而首頁(yè)中就返回了一個(gè)配置文件的名字伐坏,這個(gè)配置文件放在res/raw下的。一切的黑科技都從配置文件開(kāi)始

這里寫圖片描述

我們來(lái)看看配置文件長(zhǎng)什么樣握联。就是一個(gè)很簡(jiǎn)單的json文件桦沉,為了方便截圖我收縮了一部分。

這里寫圖片描述

上面的文件對(duì)應(yīng)于這個(gè)類

這里寫圖片描述

而JsonAnalysisConfig定義如下:

這里寫圖片描述

例子

可能大家還不是很清楚金闽,我給大家做一個(gè)例子纯露,大家就明白了。以解析生成這個(gè)為例:

這里寫圖片描述

首先整體的數(shù)據(jù)結(jié)構(gòu)如下

這里寫圖片描述

我們關(guān)心的是這一部分

這里寫圖片描述

使用它去生成一個(gè)javabean,名字就叫channelItem可以使用Android Studio的Gson生成插件代芜。

這里寫圖片描述

接著我們編寫ViewHolder埠褪。

這里寫圖片描述

這是源碼很短,很簡(jiǎn)單實(shí)現(xiàn)了解耦:

package com.zgh.smartdemo.viewholder;

import android.content.Context;


import com.zgh.smartdemo.R;
import com.zgh.smartdemo.adapter.ChannelAdapter;
import com.zgh.smartdemo.bean.ChannelItem;
import com.zgh.smartdemo.util.ClickHelper;
import com.zgh.smartdemo.view.ChannelPageIndicator;
import com.zgh.smartdemo.view.PageGridView;
import com.zgh.smartlibrary.adapter.SmartAdapter;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by zhuguohui on 2016/8/17.
 */
public class ChannelViewHolder extends SmartAdapter.SmartViewHolder<Object> {


    @Override
    public boolean isMyType(Object item) {
        if (item instanceof List) {
            List list = (List) item;
            for (Object o : list) {
                if (o == null) {
                    continue;
                }
                if (!(o instanceof ChannelItem)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    @Override
    public int getLayoutId() {
        return R.layout.layout_channel;
    }


    protected PageGridView pageGridView;
    ChannelPageIndicator channelPageIndicator;
    ChannelAdapter adapter;
    List<ChannelItem> channels = new ArrayList<>();

    @Override
    public void updateView(Context context, Object item) {
        List<ChannelItem> channels = (List<ChannelItem>) item;
        this.channels.clear();
        this.channels.addAll(channels);
        if (adapter == null) {
            adapter = new ChannelAdapter(context, this.channels, getColums());
            pageGridView.setAdapter(adapter);
            pageGridView.setPageIndicator(channelPageIndicator);
            pageGridView.setOnItemClickListener(new PageGridView.OnItemClickListener() {
                @Override
                public void onItemClick(PageGridView pageGridView, int position) {
                    ClickHelper.onClick(ChannelViewHolder.this.channels.get(position));
                }
            });
        } else {
            adapter.notifyDataSetChanged();
        }

    }

    protected int getColums() {
        return 4;
    }
}

最后講我們的這些信息記錄到配置文件中

這里寫圖片描述

需要說(shuō)明的是jsonLocation挤庇,它的值是

//{表示解析一個(gè)對(duì)象钞速,[代表解析一個(gè)數(shù)據(jù),后面是數(shù)據(jù)的名字
//而[name:0 代表解析一個(gè)名叫name的json數(shù)據(jù)下面的第一個(gè)元素
{response[centers

我們來(lái)看看解析過(guò)程

這里寫圖片描述

如果不想被自動(dòng)填充為L(zhǎng)ist則在配置文件中設(shè)置如下屬性

這里寫圖片描述

打開(kāi)斷點(diǎn)看看數(shù)據(jù)解析出來(lái)的樣子

這里寫圖片描述

更多細(xì)節(jié)大家看Demo吧

個(gè)性化配置

1.數(shù)據(jù)解析器

覆蓋SmartListFragment的這個(gè)方法可以替換自己的數(shù)據(jù)解析器

這里寫圖片描述

前提實(shí)現(xiàn)這個(gè)接口

這里寫圖片描述

目前有一個(gè)默認(rèn)的實(shí)現(xiàn)

package com.zgh.smartlibrary.net.impl;

import android.content.Context;


import com.zgh.smartlibrary.net.NetRequest;
import com.zgh.smartlibrary.net.NetRequestHandler;
import com.zgh.smartlibrary.util.FileUtil;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.builder.GetBuilder;
import com.zhy.http.okhttp.builder.HasParamsable;
import com.zhy.http.okhttp.builder.OkHttpRequestBuilder;
import com.zhy.http.okhttp.builder.PostFormBuilder;
import com.zhy.http.okhttp.callback.StringCallback;

import java.util.Map;

import okhttp3.Call;

/**
 * Created by zhuguohui on 2016/9/6.
 */
public class SmartNetRequestHandler implements NetRequestHandler {
    private final Context mContext;
    private String HTTP_HEAD = "http";
    private String HTTPS_HEAD = "https";
    private String RAW_HEAD="raw://";

    public SmartNetRequestHandler(Context context){
        mContext=context;
    }

    @Override
    public void handleNetRequest(final NetRequest netRequest) {
        String url = netRequest.getUrl();

        boolean isHttpRequest = false;
        if (url != null && url.length() > 5) {

            if (url.toLowerCase().startsWith(HTTP_HEAD) || url.toLowerCase().startsWith(HTTPS_HEAD)) {
                isHttpRequest = true;
            }
        }
        if(netRequest.getMethod()==null){
            netRequest.setMethod(NetRequest.METHOD.GET);
        }
        if (isHttpRequest) {
            GetBuilder getBuilder = null;
            PostFormBuilder postFormBuilder = null;
            OkHttpRequestBuilder requestBuilder;
            HasParamsable hasParamsable;
            switch (netRequest.getMethod()) {
                case GET:
                    getBuilder = OkHttpUtils.get();
                    break;
                case POST:
                    postFormBuilder = OkHttpUtils.post();
                    break;
            }
            requestBuilder = getBuilder != null ? getBuilder : postFormBuilder;
            if (requestBuilder == null) {
                onError(netRequest, "不支持的協(xié)議嫡秕!");
                return;
            }
            hasParamsable = getBuilder != null ? getBuilder : postFormBuilder;
            requestBuilder.url(url);
            Map<String, String> params = netRequest.getParams();
            if (params != null && params.size() > 0) {
                for (String key : params.keySet()) {
                    hasParamsable.addParams(key, params.get(key));
                }
            }
            requestBuilder.build().execute(new StringCallback() {
                @Override
                public void onError(Call call, Exception e, int id) {
                    SmartNetRequestHandler.this.onError(netRequest, e.getMessage());
                }

                @Override
                public void onResponse(String response, int id) {
                    onSuccess(netRequest,response);
                }
            });
        } else {
            if(url.toLowerCase().startsWith(RAW_HEAD)){
                String rawName = url.substring(RAW_HEAD.length());
                String s = FileUtil.readRaw(mContext, rawName);
                onSuccess(netRequest, s);
            }else{
                onError(netRequest,"不支持的協(xié)議渴语!");
                return;
            }
        }

    }

    public void onError(NetRequest request, String msg) {
        if (request != null && request.getResultListener() != null) {
            request.getResultListener().onError(msg);
        }
    }

    public void onSuccess(NetRequest request, Object data) {
        if (request != null && request.getResultListener() != null) {
            request.setData(data);
            request.getResultListener().onSuccess(request);
        }
    }

    @Override
    public void cancelNetRequest(NetRequest netRequest) {

    }
}

2.下拉刷控件替換

覆蓋這個(gè)方法

 protected  ListViewUpdateManger getUpdateManager(Context context){
        return new PullToRefreshManger(context);
    }

實(shí)現(xiàn)這個(gè)接口

/**
 * 管理listview的上拉加載與下拉刷新
 * Created by zhuguohui on 2016/9/5.
 */
public interface ListViewUpdateManger {

    ListView getListView();

    View getView();

    void setState(IPagePolicy.PageState state);

    void setAdapter(BaseAdapter adapter);

    void setUpdateListener(UpdateListener listener);

    interface UpdateListener {
        void pullUp();
        void pullDown();
    }

    void updateComplete();

    void update(boolean showAnimation);

}

有一個(gè)默認(rèn)的實(shí)現(xiàn)PullToRefreshManger大家可以看看源碼

對(duì)數(shù)據(jù)進(jìn)行修改

這里寫圖片描述

對(duì)網(wǎng)絡(luò)請(qǐng)求修改

比如添加統(tǒng)一的token之類的

這里寫圖片描述

對(duì)頁(yè)面修改

1.代碼部分

這里寫圖片描述

2.布局部分

這里寫圖片描述

實(shí)現(xiàn)

東西太多看源碼吧

源碼

SmartDemo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市昆咽,隨后出現(xiàn)的幾起案子驾凶,更是在濱河造成了極大的恐慌牙甫,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件调违,死亡現(xiàn)場(chǎng)離奇詭異窟哺,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)翰萨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門脏答,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)糕殉,“玉大人亩鬼,你說(shuō)我怎么就攤上這事“⒌” “怎么了雳锋?”我有些...
    開(kāi)封第一講書人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)羡洁。 經(jīng)常有香客問(wèn)我玷过,道長(zhǎng),這世上最難降的妖魔是什么筑煮? 我笑而不...
    開(kāi)封第一講書人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任辛蚊,我火速辦了婚禮,結(jié)果婚禮上真仲,老公的妹妹穿的比我還像新娘袋马。我一直安慰自己,他們只是感情好秸应,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布虑凛。 她就那樣靜靜地躺著,像睡著了一般软啼。 火紅的嫁衣襯著肌膚如雪桑谍。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,231評(píng)論 1 299
  • 那天祸挪,我揣著相機(jī)與錄音锣披,去河邊找鬼。 笑死贿条,一個(gè)胖子當(dāng)著我的面吹牛雹仿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播闪唆,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼盅粪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了悄蕾?” 一聲冷哼從身側(cè)響起票顾,我...
    開(kāi)封第一講書人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤础浮,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后奠骄,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體豆同,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年含鳞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了影锈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蝉绷,死狀恐怖鸭廷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情熔吗,我是刑警寧澤辆床,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站桅狠,受9級(jí)特大地震影響讼载,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜中跌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一咨堤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧漩符,春花似錦一喘、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至灼伤,卻和暖如春触徐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背狐赡。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工撞鹉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人颖侄。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓鸟雏,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親览祖。 傳聞我的和親對(duì)象是個(gè)殘疾皇子孝鹊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,085評(píng)論 25 707
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)展蒂,斷路器又活,智...
    卡卡羅2017閱讀 134,652評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,806評(píng)論 6 342
  • 不懂愛(ài)苔咪,渴望愛(ài),一直在找尋愛(ài)柳骄。 我朋友說(shuō)团赏,我夢(mèng)到的小紅帽,就是一直在找尋的象征耐薯。我說(shuō)舔清,小紅帽充滿希望,但很容易相信...
    法棍紅辣椒閱讀 124評(píng)論 0 0
  • 這幾副是前一段生病的時(shí)候畫的曲初,什么都不懂的情況下買的第一套彩鉛筆体谒!因?yàn)闆](méi)有基礎(chǔ)畫的不太隨人意,會(huì)多看多加練習(xí)复斥!
    Eleni閱讀 193評(píng)論 0 2