手把手教你從零開(kāi)始做一個(gè)好看的 APP

本篇文章已授權(quán)為微信公眾號(hào) code小生 發(fā)布
轉(zhuǎn)載請(qǐng)注明出處:http://www.reibang.com/p/8d2d74d6046f

前言

從零開(kāi)始刚夺,手把手帶你實(shí)現(xiàn)一個(gè)「專(zhuān)注睡前的 APP」榛丢。睡覺(jué)之前如果能有一個(gè) APP挽铁,能讓我們寫(xiě)一寫(xiě)這一天的見(jiàn)聞或者心得坑填,同時(shí)又能看一會(huì)段子拳锚、瞄一會(huì)好看的妹子熄浓,放松一下疲憊的身心那該多好氧秘,這也是我完成這個(gè) APP 的原因紧武。APP 的全部代碼我已經(jīng)分享到 Github 上了,需要的直接 點(diǎn)擊這里敏储,如果喜歡的話阻星,麻煩給個(gè) star,謝謝啦已添。

本文為這一系列文章的總述妥箕,如果覺(jué)得篇幅過(guò)長(zhǎng),請(qǐng)點(diǎn)擊下面的連接

手把手教你從零開(kāi)始做一個(gè)好看的 APP - Day one

手把手教你從零開(kāi)始做一個(gè)好看的 APP - Day two

手把手教你從零開(kāi)始做一個(gè)好看的 APP - Day three

手把手教你從零開(kāi)始做一個(gè)好看的 APP - Day four

手把手教你從零開(kāi)始做一個(gè)好看的 APP - Day five

在開(kāi)始寫(xiě)正文之前更舞,先來(lái)一波效果的展示畦幢,看看五天過(guò)后我們能實(shí)現(xiàn)怎樣的效果


SleepHelper.gif

本次的教程分為 5 天,內(nèi)容分別為:

  • Day one缆蝉,準(zhǔn)備

    • 功能需求
    • 可行性分析
  • Day two宇葱,UI 及公共類(lèi)的封裝

    • 界面的設(shè)計(jì)及實(shí)現(xiàn)
    • 公共類(lèi)的實(shí)現(xiàn)
  • Day three,日記模塊

    • 日記的展示
    • 懸浮菜單的實(shí)現(xiàn)
    • 日記增刪改的實(shí)現(xiàn)
  • Day four刊头,妹子模塊

    • 圖片的獲取
    • 圖片的展示
    • 詳情頁(yè)面的展示
  • Day five黍瞧,段子模塊

    • 段子數(shù)據(jù)的獲取
    • 段子的顯示

Day one


俗話說(shuō),萬(wàn)事開(kāi)頭難原杂,在開(kāi)始敲代碼之前印颤,先讓我們來(lái)做一些必要的準(zhǔn)備,這樣才能事半功倍嘛穿肄!

一年局、功能需求

既然要做一個(gè) APP,那我們首先還是得把 APP 的功能都列出來(lái)咸产,有了方向才能更好的努力矢否,因?yàn)槲蚁胱龅氖且粋€(gè)專(zhuān)門(mén)給睡覺(jué)前用的 APP,所以我覺(jué)得應(yīng)該有以下的這些功能

  • 1脑溢、日記的增刪改
  • 2僵朗、顯示一些有趣好玩的段子
  • 3、瀑布流展示漂亮的妹子
  • 4、保存日記的內(nèi)容以及緩存妹子圖片

雖然說(shuō)需求不多衣迷,但是卻要運(yùn)用到網(wǎng)絡(luò)、數(shù)據(jù)存儲(chǔ)酱酬、圖片緩存壶谒、UI 設(shè)計(jì)等內(nèi)容,相信整個(gè) APP 完成下來(lái)膳沽,必定能鞏固我們的 Android 基礎(chǔ)汗菜。

二、可行性分析

我們這個(gè) APP 主要有三個(gè)模塊挑社,日記模塊主要是運(yùn)用到了數(shù)據(jù)庫(kù)的知識(shí)壹无,難度不大贺喝。但是,段子模塊和妹子模塊的數(shù)據(jù)要從哪來(lái),這便是要好好考慮的了烈疚。幸好現(xiàn)在是個(gè)開(kāi)源的時(shí)代,很多的數(shù)據(jù)沟突,網(wǎng)上已經(jīng)開(kāi)源出來(lái)了揩悄。

我們先來(lái)看一下數(shù)據(jù)的內(nèi)容

group: {
        text: "教授在河邊,常潮滋恚看到兩只龜录淡,縮著一動(dòng)不動(dòng)。有天忍不住好奇油坝,問(wèn)一農(nóng)      
        民:這兩只烏龜在干嗎嫉戚?農(nóng)民說(shuō):他們?cè)趐k。教授不解地問(wèn):動(dòng)都沒(méi)動(dòng)過(guò)p什么    
        k澈圈。老農(nóng)說(shuō):他們?cè)诒日l(shuí)壽命長(zhǎng)彬檀。教授說(shuō):可是殼上有甲骨文的那只,早就死了埃
        這時(shí)瞬女,另一只猛然探出頭來(lái)罵到:md凤覆,死了也不吭一聲!有甲骨文的那只也伸
        出頭來(lái):“專(zhuān)家說(shuō)啥你信啥1",

        user: {
              user_id: 4669064575,

              name: "饅頭啊",

              avatar_url: "http://p3.pstatp.com/medium/6237/7969345239",
},

          content: "教授在河邊拆魏,常扯㈣耄看到兩只龜,縮著一動(dòng)不動(dòng)渤刃。有天忍不住好奇拥峦,問(wèn)        
           一農(nóng)民:這兩只烏龜在干嗎?農(nóng)民說(shuō):他們?cè)趐k卖子。教授不解地問(wèn):動(dòng)都沒(méi)動(dòng)過(guò)
           p什么k略号。老農(nóng)說(shuō):他們?cè)诒日l(shuí)壽命長(zhǎng)。教授說(shuō):可是殼上有甲骨文的那只,早
           就死了埃這時(shí)玄柠,另一只猛然探出頭來(lái)罵到:md突梦,死了也不吭一聲!有甲骨文
           的那只也伸出頭來(lái):“專(zhuān)家說(shuō)啥你信啥1",
...  
}
{
          id: "56cc6d1d421aa95caa7076df",

          type: "福利",

          url: "http://ww1.sinaimg.cn/large/7a8aed7bgw1esxxi1vbq0j20qo0hstcu.jpg",

          used: true,

          who: "張涵宇"

}

上面那兩段代碼分別是段子和妹子模塊的 json 類(lèi)型的數(shù)據(jù)羽利,我已經(jīng)將一些沒(méi)用的字段去掉了宫患。剩下的都是我們想要的數(shù)據(jù)≌饣。可以看到段子數(shù)據(jù)中娃闲,有著段子的內(nèi)容,以及發(fā)布者的頭像和名字匾浪。而妹子數(shù)據(jù)中有著圖片的 url皇帮、id、以及圖片的類(lèi)型蛋辈。相信有了這么豐富的數(shù)據(jù)属拾,我們想要完成這個(gè) APP 也是有底氣了。

Day two


一冷溶、界面的設(shè)計(jì)及實(shí)現(xiàn)

既然我們想要完成一個(gè)好看的 APP捌年,那么好看的界面便是必不可少的,這里我強(qiáng)烈推薦 APP 界面的設(shè)計(jì)必須盡量遵從 Google 提出的 Material Design挂洛,在這個(gè)推薦一個(gè)能夠讓我們實(shí)現(xiàn) Material Design 變得更加簡(jiǎn)單的網(wǎng)站 material design palette礼预,我這個(gè) APP 的配色就是用這個(gè)網(wǎng)站完成的,貼幾張圖片虏劲,讓你感受一下它的強(qiáng)大

material design palette
Material Design 風(fēng)格的圖標(biāo)

借助這個(gè)網(wǎng)站便能讓我們完成 APP 的配色以及圖標(biāo)的收集托酸,為下一步功能的實(shí)現(xiàn),先打好了基礎(chǔ)柒巫,至于界面的設(shè)計(jì)就仁者見(jiàn)仁智者見(jiàn)智了励堡,篇幅有限,我就不多講了堡掏。

APP 的最終設(shè)計(jì)效果如下:


SleepHelper

二应结、公共類(lèi)的實(shí)現(xiàn)

因?yàn)檫@個(gè)項(xiàng)目有三個(gè)模塊,有一些東西其實(shí)是可以通用的泉唁,如果我們先把這些能夠通用的東西鹅龄,封裝起來(lái),供給所有的模塊調(diào)用的話亭畜,相信會(huì)大大提高我們的開(kāi)發(fā)效率扮休。

1、網(wǎng)絡(luò)工具類(lèi)的封裝

這個(gè) APP 中拴鸵,很多地方都要用到網(wǎng)絡(luò)請(qǐng)求玷坠,因此也就很有必要將網(wǎng)絡(luò)請(qǐng)求封裝起來(lái)蜗搔,因?yàn)檫@個(gè) APP 的規(guī)模比較小,因此我選擇了 Volley 這個(gè)網(wǎng)絡(luò)框架作為我們網(wǎng)絡(luò)請(qǐng)求庫(kù)八堡,把網(wǎng)絡(luò)請(qǐng)求封裝起來(lái)樟凄,哪個(gè)地方需要,調(diào)用一下就行了兄渺。對(duì)于網(wǎng)絡(luò)請(qǐng)求缝龄,我覺(jué)得每個(gè)程序員都該懂點(diǎn) HTTP,這里附上一篇有關(guān) HTTP 的文章 程序員都該懂點(diǎn) HTTP溶耘。

先讓我們來(lái)寫(xiě)個(gè)將網(wǎng)絡(luò)請(qǐng)求進(jìn)行回調(diào)的接口

public interface VolleyResponseCallback {
    void onSuccess(String response);
    void onError(VolleyError error);
}

然后將網(wǎng)絡(luò)請(qǐng)求封裝起來(lái)

public class VolleyHelper {

    /**
     * 用于發(fā)送 Get 請(qǐng)求的封裝方法
     *
     * @param context Activity 的實(shí)例
     * @param url 請(qǐng)求的地址
     * @param callback 用于網(wǎng)絡(luò)回調(diào)的接口
     */
    public static void sendHttpGet(Context context, String url, final VolleyResponseCallback callback){
        RequestQueue requestQueue = Volley.newRequestQueue(context);
        StringRequest stringRequest = new StringRequest(url
                , new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                callback.onSuccess(s);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                callback.onError(error);
            }
        });
        requestQueue.add(stringRequest);
    }


}
2、Json 解析的幫助類(lèi)

因?yàn)槲覀冞@個(gè) APP 中服鹅,獲取到的數(shù)據(jù)都是 Json 格式的凳兵,因此也就有必要將有關(guān)的 Json 解析封裝成一個(gè)工具類(lèi),傳入一個(gè) String 類(lèi)型的數(shù)據(jù)企软,直接得到數(shù)據(jù)實(shí)體類(lèi)的 List庐扫。

public class CommonParser {

    /**
     * 用來(lái)解析列表性的JSON數(shù)據(jù)
     * 如:
     * {"success":true,"fileList":[{"filename":"文件名1","fileSize":"文件大小1"},
     * {"filename":"文件名2","fileSize":"文件大小2"}]}
     *
     * @param result     網(wǎng)絡(luò)返回來(lái)的JSON數(shù)據(jù)   比如:上面的整串?dāng)?shù)據(jù)
     * @param successKey 判斷網(wǎng)絡(luò)是否成功的字段  比如:上面的success字段
     * @param arrKey     列表的字段            比如:上面的fileList字段
     * @param clazz      需要解析成的Bean類(lèi)型
     * @param <T>        需要解析成的Bean類(lèi)型
     * @return
     */
    public static <T> List<T> parseForList(String result, String successKey, String arrKey, Class<T> clazz) {
        List<T> list = new ArrayList<>();
        JSONObject rootJsonObject = null;
        try {
            rootJsonObject = new JSONObject(result);
            if (rootJsonObject.getBoolean(successKey)) {
                JSONArray rootJsonArray = rootJsonObject.getJSONArray(arrKey);
                Gson g = new Gson();
                for (int i = 0; i < rootJsonArray.length(); i++) {
                    T t = g.fromJson(rootJsonArray.getJSONObject(i).toString(), clazz);
                    list.add(t);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return list;
    }
}
3、HomeActivity(主頁(yè)面)的封裝

主頁(yè)面我用的是 TabLayout + ViewPager + Fragment仗哨,也是現(xiàn)在主流 APP 主頁(yè)面的顯示方式形庭。主界面底部是我們?nèi)齻€(gè)模塊的圖標(biāo)和名稱,通過(guò)左右滑動(dòng)能實(shí)現(xiàn)界面的跳轉(zhuǎn)厌漂。

底部圖標(biāo)的實(shí)體類(lèi) CommonTabBean
public class CommonTabBean implements CustomTabEntity{

    private int selectedIcon;
    private int unselectedIcon;
    private String title;

    public CommonTabBean(String title){
        this.title = title;
    }

    public CommonTabBean(String title, int selectedIcon, int unselectedIcon) {
        this.title = title;
        this.selectedIcon = selectedIcon;
        this.unselectedIcon = unselectedIcon;
    }

    @Override
    public String getTabTitle() {
        return title;
    }

    @Override
    public int getTabSelectedIcon() {
        return selectedIcon;
    }

    @Override
    public int getTabUnselectedIcon() {
        return unselectedIcon;
    }
}
ViewPager + Fragment 通用的 Adapter
public class CommonPagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> mFragments;

    public CommonPagerAdapter(FragmentManager fragmentManager, List<Fragment> mFragments){
        super(fragmentManager);
        this.mFragments = mFragments;
    }

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

    @Override
    public int getCount() {
        return mFragments.size();
    }
}

Day three


關(guān)于日記模塊的實(shí)現(xiàn)萨醒,其實(shí)我是復(fù)用了以前寫(xiě)過(guò)的一個(gè)日記 APP,具體的思路和做法苇倡,可以參考我的這篇文章 Android 一款十分簡(jiǎn)潔富纸、優(yōu)雅的日記 APP

Day four


一、圖片的獲取

1旨椒、根據(jù)返回的數(shù)據(jù)來(lái)編寫(xiě)圖片的實(shí)體類(lèi)
public class MeiziBean {

    @SerializedName("_id")
    private String id;
    @SerializedName("url")
    private String imageUrl;
    @SerializedName("who")
    private String who;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public MeiziBean(String imageUrl){
        this.imageUrl = imageUrl;
    }
}
2晓褪、圖片的展示

可以看到我是用瀑布流的方式來(lái)實(shí)現(xiàn)圖片的展示,效果還不錯(cuò)综慎,但其實(shí)實(shí)現(xiàn)起來(lái)也是很簡(jiǎn)單的

先寫(xiě)個(gè)圖片的布局作為 RecyclerView 的 Item

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

                <ImageView
                    android:id="@+id/item_iv_meizi"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_centerHorizontal="true"
                    android:layout_centerVertical="true"
                    />
</android.support.v7.widget.CardView>

可以看到我在 ImageView 的外面加了一個(gè) CardView涣仿,這個(gè)一種卡片式布局,能讓圖片看起來(lái)就像一張卡片一樣示惊,相當(dāng)?shù)膬?yōu)雅好港、美觀。

接著編寫(xiě) Adapter米罚,將數(shù)據(jù)和界面進(jìn)行綁定

public class MeiziAdapter extends RecyclerView.Adapter<MeiziAdapter.MeiziViewHolder> {

    private List<MeiziBean> mMeiziBeanList;
    private Fragment mFragment;

    public MeiziAdapter(List<MeiziBean> mMeiziBeanList, Fragment mFragment){
        this.mMeiziBeanList = mMeiziBeanList;
        this.mFragment = mFragment;
    }

    @Override
    public MeiziViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_meizi, null);
        return new MeiziViewHolder(view);
    }

    @Override
    public void onBindViewHolder(MeiziViewHolder holder, final int position) {

        Glide.with(mFragment)
                .load(mMeiziBeanList.get(position).getImageUrl())
                .fitCenter()
                .dontAnimate()
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(holder.mIvMeizi);

        holder.mIvMeizi.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ArrayList<String> resultList = new ArrayList<String>();
                for (MeiziBean meiziBean : mMeiziBeanList) {
                    resultList.add(meiziBean.getImageUrl());
                }
                DetailActivity.startActivity(mFragment.getActivity(), resultList, position);

            }
        });

    }

    @Override
    public int getItemCount() {
        if(mMeiziBeanList.size() > 0){
            return mMeiziBeanList.size();
        }
        return 0;
    }

    public static class MeiziViewHolder extends RecyclerView.ViewHolder{

        ImageView mIvMeizi;

        public MeiziViewHolder(View itemView) {
            super(itemView);
            mIvMeizi = (ImageView) itemView.findViewById(R.id.item_iv_meizi);
        }
    }
}

最后在 Fragment 進(jìn)行數(shù)據(jù)的獲取媚狰,以及布局的初始化就行了

public class MeiziFragment extends Fragment {

    ......

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_meizi, container, false);
        ButterKnife.bind(this, view);
        initView();
        refreshMeizi();
        return view;
    }

    /**
     * 刷新當(dāng)前界面
     */
    private void refreshMeizi() {
        mRefresh.setColorSchemeResources(R.color.colorPrimary);
        mRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                initView();
                mRefresh.setRefreshing(false);
            }
        });
    }

    private void initView() {
        VolleyHelper.sendHttpGet(getActivity(), MeiziApi.getMeiziApi(), new VolleyResponseCallback() {
            @Override
            public void onSuccess(String s) {
                response = s;
                meiziBeanList = GsonHelper.getMeiziBean(response);
                mRvShowMeizi.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
                Collections.shuffle(meiziBeanList);
                mRvShowMeizi.setAdapter(new MeiziAdapter(meiziBeanList, MeiziFragment.this));
            }

            @Override
            public void onError(VolleyError error) {
                Logger.d(error);
            }
        });
    }

3、詳情頁(yè)面的展示

干巴巴的阔拳,整個(gè)模塊只能顯示妹子的圖片怎么行呢U腹隆@噜汀!怎么著也得能查看大圖辨宠,根據(jù)手勢(shì)放大縮小遗锣,以及瀏覽下一張圖片才行嘛,說(shuō)干就干嗤形。

因?yàn)閳D片需要有根據(jù)手勢(shì)來(lái)放大縮小的功能精偿,因此我便想到了 PhotoView,這是網(wǎng)上一個(gè)大神寫(xiě)的赋兵,繼承自 ImageView 的一個(gè)自定義控件笔咽。圖片加載我用的是
Glide,如果沒(méi)了解過(guò)這個(gè)庫(kù)的霹期,強(qiáng)烈推薦叶组,一行代碼就能搞定圖片加載,你確定不研究一下历造。這里附上一篇有關(guān) Glide 的文章 Glide 一個(gè)強(qiáng)大的圖片加載框架

public class DetailFragment extends Fragment {

    public static DetailFragment newInstance(String imageUrl) {
        DetailFragment fragment = new DetailFragment();
        Bundle bundle = new Bundle();
        bundle.putString(IMAGE_URL, imageUrl);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_detail, container, false);
        ButterKnife.bind(this, view);
        Bundle bundle = getArguments();
        String imageUrl = bundle.getString(IMAGE_URL);
        Glide.with(this).load(imageUrl).into(mPvShowPhoto);
        mPvShowPhoto.setOnPhotoTapListener(new PhotoViewAttacher.OnPhotoTapListener() {
            @Override
            public void onPhotoTap(View view, float v, float v1) {
                getActivity().finish();
            }

            @Override
            public void onOutsidePhotoTap() {

            }
        });
        return view;
    }
}

Day five


一甩十、段子數(shù)據(jù)的獲取

段子數(shù)據(jù)的獲取其實(shí)跟妹子模塊的方法基本一樣

先編寫(xiě)實(shí)體類(lèi)

public class DuanziBean {

    @SerializedName("group")
    private GroupBean groupBean;
    private String type;

    public GroupBean getGroupBean() {
        return groupBean;
    }

    public void setGroupBean(GroupBean groupBean) {
        this.groupBean = groupBean;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
    
}
public class GroupBean {

    private String text;
    private long id;
    private UserBean user;

    public String getText() {
        return text;
    }

    public long getId() {
        return id;
    }

    public UserBean getUser() {
        return user;
    }

    public static class UserBean {

        private long user_id;
        private String name;
        private String avatar_url;

        public String getName() {
            return name;
        }

        public String getAvatar_url() {
            return avatar_url;
        }

    }
}

寫(xiě)好實(shí)體類(lèi)之后,使用我們之前已經(jīng)封裝好的網(wǎng)絡(luò)請(qǐng)求工具以及解析工具吭产,便能將返回的數(shù)據(jù)侣监,解析成一個(gè)包含段子實(shí)體類(lèi)的 List。

二臣淤、段子的顯示

老規(guī)矩橄霉,先寫(xiě)個(gè) RecyclerView 的 Item

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:paddingLeft="8dp"
        >

        <de.hdodenhof.circleimageview.CircleImageView
            android:id="@+id/duanzi_civ_avatar"
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:src="@drawable/avatar"
            android:layout_gravity="center"
            />

        <TextView
            android:id="@+id/duanzi_tv_author"
            android:paddingLeft="8dp"
            android:paddingStart="8dp"
            android:layout_width="match_parent"
            android:layout_height="16dp"
            android:text="DeveloperHaoz"
            android:layout_gravity="center_vertical"
            />

    </LinearLayout>

    <TextView
        android:id="@+id/duanzi_tv_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="10dp"
        android:paddingLeft="40dp"
        android:paddingRight="10dp"
        android:text=""
        />
    <include layout="@layout/layout_app_divide"/>

</LinearLayout>

然后編寫(xiě)將數(shù)據(jù)和界面進(jìn)行綁定的 Adapter

public class DuanziAdapter extends RecyclerView.Adapter<DuanziAdapter.DuanziViewHolder>{

    private Fragment mFragment;
    private List<DuanziBean> mDuanziBeanList;

    public DuanziAdapter(Fragment fragment, List<DuanziBean> duanziBeanList){
        this.mFragment = fragment;
        this.mDuanziBeanList = duanziBeanList;
    }

    @Override
    public DuanziViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_duanzi, null);
        return new DuanziViewHolder(view);
    }

    @Override
    public void onBindViewHolder(DuanziViewHolder holder, int position) {
        try {
            DuanziBean duanziBean = mDuanziBeanList.get(position);
            Glide.with(mFragment).load(duanziBean.getGroupBean().getUser().getAvatar_url()).into(holder.mCivAvatar);
            holder.mTvContent.setText(duanziBean.getGroupBean().getText());
            holder.mTvAuthor.setText(duanziBean.getGroupBean().getUser().getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public int getItemCount() {
        return mDuanziBeanList.size();
    }

    public static class DuanziViewHolder extends RecyclerView.ViewHolder{

        private CircleImageView mCivAvatar;
        private TextView mTvAuthor;
        private TextView mTvContent;

        public DuanziViewHolder(View itemView) {
            super(itemView);
            mCivAvatar = (CircleImageView) itemView.findViewById(R.id.duanzi_civ_avatar);
            mTvAuthor = (TextView) itemView.findViewById(R.id.duanzi_tv_author);
            mTvContent = (TextView) itemView.findViewById(R.id.duanzi_tv_content);
        }
    }


}

最后段子頁(yè)面中進(jìn)行數(shù)據(jù)和獲取以及界面的初始化

public class DuanziFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_duanzi, container, false);
        ButterKnife.bind(this, view);
        initView();
        initRefresh();
        return view;
    }

    private void initRefresh() {
        mRefresh.setColorSchemeResources(R.color.colorPrimary);
        mRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                initView();
                mRefresh.setRefreshing(false);
            }
        });
    }

    private void initView() {
        VolleyHelper.sendHttpGet(getActivity(), DuanziApi.GET_DUANZI, new VolleyResponseCallback() {
            @Override
            public void onSuccess(String response) {
                List<DuanziBean> mDuanziBeanList = GsonHelper.getDuanziBeanList(response);
                mDuanziBeanList.remove(3);
                mRvShowDuanzi.setLayoutManager(new LinearLayoutManager(getActivity()));
                mRvShowDuanzi.setAdapter(new DuanziAdapter(DuanziFragment.this, mDuanziBeanList));
            }

            @Override
            public void onError(VolleyError error) {
                Logger.d(error);
            }
        });
    }

}

以上便是本文的全部?jī)?nèi)容,這個(gè) APP 的全部代碼我已經(jīng)分享到 Github 上了邑蒋,如果覺(jué)得對(duì)你有幫助的話酪劫,就賞個(gè) star 吧。


猜你喜歡

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市遮咖,隨后出現(xiàn)的幾起案子滩字,更是在濱河造成了極大的恐慌,老刑警劉巖御吞,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件麦箍,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡陶珠,警方通過(guò)查閱死者的電腦和手機(jī)挟裂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)揍诽,“玉大人诀蓉,你說(shuō)我怎么就攤上這事栗竖。” “怎么了渠啤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵狐肢,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我沥曹,道長(zhǎng)份名,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任妓美,我火速辦了婚禮僵腺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘壶栋。我一直安慰自己辰如,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布委刘。 她就那樣靜靜地躺著丧没,像睡著了一般鹰椒。 火紅的嫁衣襯著肌膚如雪锡移。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,679評(píng)論 1 305
  • 那天漆际,我揣著相機(jī)與錄音淆珊,去河邊找鬼。 笑死奸汇,一個(gè)胖子當(dāng)著我的面吹牛施符,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播擂找,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼戳吝,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了贯涎?” 一聲冷哼從身側(cè)響起听哭,我...
    開(kāi)封第一講書(shū)人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎塘雳,沒(méi)想到半個(gè)月后陆盘,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡败明,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年隘马,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妻顶。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡酸员,死狀恐怖蜒车,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情沸呐,我是刑警寧澤醇王,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站崭添,受9級(jí)特大地震影響寓娩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜呼渣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一棘伴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧屁置,春花似錦焊夸、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至使鹅,卻和暖如春揪阶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背患朱。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工鲁僚, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人裁厅。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓冰沙,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親执虹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拓挥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

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