上路传送眼:

Android练手小项目(KTReader)基于mvp架构(二)

下路传送眼:

Android练手小项目(KTReader)基于mvp架构(四)

GIthub地址: https://github.com/yiuhet/KTReader

上篇文章中我们完成了知乎日报内容的fragment。
而这次我们要做的的就是知乎日报详情页。

惯例先上效果图:


效果图

准备工作

  • 添加依赖

compile 'com.jude:swipebackhelper:3.1.2' //右滑关闭详情页

  • 工具类
    utils.WebUtil.class(返回html结果的工具类):
public class WebUtil {    private WebUtil() {    }    public static final String BASE_URL = "file:///android_asset/";    public static final String MIME_TYPE = "text/html";    public static final String ENCODING = "utf-8";    public static final String FAIL_URL = "http//:daily.zhihu.com/";    private static final String CSS_LINK_PATTERN = " ";    private static final String DIV_IMAGE_PLACE_HOLDER = "class=\"img-place-holder\"";    public static String buildHtmlWithCss(String html, List cssUrls) {        StringBuilder result = new StringBuilder();        for (String cssUrl : cssUrls) {            result.append(String.format(CSS_LINK_PATTERN, cssUrl));        }        result.append(html.replace(DIV_IMAGE_PLACE_HOLDER, ""));        return result.toString();    }}

Model层

  • 模型实体类ZhihuDetail直接使用GsonFormat工具快速生成
    (model.entity.ZhihuDetail)

  • 知乎日报Model接口
    model.ZhihuDetailModel:

public interface ZhihuDetailModel {    void loadDetail(String id, OnZhihuDetailListener listener);}
  • 获取日报详情的Model实现
public class ZhihuDetailModelImp1 implements ZhihuDetailModel {    // /*获取日报详情的Model实现*/    private ZhihuApi mZhihuApiService; //请求服务    private ZhihuDetail mZhihuDetail;    public ZhihuDetailModelImp1() {        mZhihuDetail = new ZhihuDetail();        mZhihuApiService = RetrofitManager                .getInstence()                .getRetrofit("http://news-at.zhihu.com/api/4/news/")                .create(ZhihuApi.class); //创建请求服务    }    public ZhihuDetail getDetail() {        return mZhihuDetail;    }    @Override    public void loadDetail(String id, final OnZhihuDetailListener listener) {        if (mZhihuApiService != null) {            mZhihuApiService.getDetail(id)                    .subscribeOn(Schedulers.io())                    .observeOn(AndroidSchedulers.mainThread())                    .subscribe(new Observer() {                        @Override                        public void onSubscribe(@NonNull Disposable d) {                        }                        @Override                        public void onNext(@NonNull ZhihuDetail zhihuDetail) {                            mZhihuDetail = zhihuDetail;                            listener.onLoadZhihuDetailSuccess(zhihuDetail);//加载成功时 回调接口方法。                        }                        @Override                        public void onError(@NonNull Throwable e) {                            listener.onLoadDataError(e.toString());//加载失败时 回调接口方法。                        }                        @Override                        public void onComplete() {                        }                    });        }    }}

View层

  • 创建回调接口
    view.ZhihuDetailView:
public interface ZhihuDetailView {    void onStartGetData();    void onGetDetailSuccess(ZhihuDetail zhihuDetail);    void onGetDetailFailed(String error);}
  • 创建ZhihuDetailActivity
    详情页包含的新知识点全在ZhihuDetailActivity上,所涵盖的知识有:
    • WebView的使用
    • 右滑关闭activity(也不算知识点,因为使用别人的开源,以后要改写成自己的)
    • CollapsingToolbarLayout 和NestedScrollView的使用

附上一些资料:
WebView·开车指南
看,这个工具栏能伸缩折叠——Android CollapsingToolbarLayout使用
[Jude95/SwipeBackHelper]

具体解释全都在代码注释里。
直接上代码
ui.activity.ZhihuDetailActivity .class:

public class ZhihuDetailActivity extends MVPBaseActivity implements ZhihuDetailView {    @BindView(R.id.toolbar)    Toolbar mToolbar;    @BindView(R.id.toolbar_layout)    CollapsingToolbarLayout mToolbarLayout;    @BindView(R.id.prograss)    ProgressBar mPrograss;    @BindView(R.id.wv_zhihu)    WebView mWvZhihu;    @BindView(R.id.fab)    FloatingActionButton mFab;    @BindView(R.id.iv_title)    ImageView mIvTitle;    private String mZhihuId;    @Override    protected ZhihuDetailPresenterImp1 createPresenter() {        return new ZhihuDetailPresenterImp1(this);    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        SwipeBackHelper.onCreate(this);        ButterKnife.bind(this);        initToolbar();        initView();    }    private void initToolbar() {        setSupportActionBar(mToolbar);        getSupportActionBar().setDisplayHomeAsUpEnabled(true);        getSupportActionBar().setHomeButtonEnabled(true);    }    private void initView() {        mZhihuId = getIntent().getStringExtra("ZHIHUID");        mPresenter.getDetail(mZhihuId);        mFab.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                Snackbar.make(view, "已添加进收藏夹(待做功能)", Snackbar.LENGTH_LONG)                        .setAction("Action", null).show();            }        });        mWvZhihu.setVerticalScrollBarEnabled(true);        mWvZhihu.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_INSET);        WebSettings settings = mWvZhihu.getSettings();        //设置应用缓存路径,这个路径必须是可以让app写入文件的。该方法应该只被调用一次,重复调用会被无视~        settings.setAppCachePath(getCacheDir().getAbsolutePath() + "/webViewCache");        settings.setAppCacheEnabled(true); //启用应用缓存。        settings.setDatabaseEnabled(true); //启用数据库缓存。        settings.setDomStorageEnabled(true); //开启DOM缓存        //用来设置WebView的缓存模式(这里使用的是 只要缓存可用就加载缓存)        settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);        settings.setJavaScriptEnabled(true); //设置WebView可以运行JavaScript。        settings.setBuiltInZoomControls(true);//显示或不显示缩放按钮(wap网页不支持)。        //指定WebView的页面布局显示形式,调用该方法会引起页面重绘        settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);        mWvZhihu.setWebChromeClient(new WebChromeClient());    }    @Override    protected int getLayoutRes() {        return R.layout.activity_zhihu_detail;    }    @Override    public void onStartGetData() {        mPrograss.setVisibility(View.VISIBLE);    }    @Override    public void onGetDetailSuccess(ZhihuDetail zhihuDetail) {        mPrograss.setVisibility(View.GONE);        mToolbarLayout.setTitle(zhihuDetail.title);        //在较为特殊的情况下,知乎日报可能将某个主题日报的站外文章推送至知乎日报首页。        if (zhihuDetail.body == null) {            mWvZhihu.loadUrl(zhihuDetail.shareUrl);        } else {            Glide.with(this).load(zhihuDetail.image).into(mIvTitle);            String data = WebUtil.buildHtmlWithCss(zhihuDetail.body, zhihuDetail.css);            mWvZhihu.loadDataWithBaseURL(WebUtil.BASE_URL, data, WebUtil.MIME_TYPE, WebUtil.ENCODING, WebUtil.FAIL_URL);        }    }    @Override    public void onGetDetailFailed(String error) {        mPrograss.setVisibility(View.GONE);        toast(error);    }    @Override    protected void onPostCreate(@Nullable Bundle savedInstanceState) {        super.onPostCreate(savedInstanceState);        SwipeBackHelper.onPostCreate(this);    }    @Override    protected void onDestroy() {        if (mWvZhihu != null) {            //webview内存泄露            ((ViewGroup) mWvZhihu.getParent()).removeView(mWvZhihu);            mWvZhihu.destroy();            mWvZhihu = null;        }        super.onDestroy();        SwipeBackHelper.onDestroy(this);    }}

另附上ZhihuDetailActivity的布局文件:

activity_zhihu_detail.xml:

                                                                    

content_zhihu_detail.xml:

                            

ZhihuDetailActivity里的fab点击事件预想是添加入收藏栏,等之后写到收藏栏功能时会完成该功能
ps:从效果图中,可以看出CollapsingToolbarLayout的title显示不全,目前还没找到解决办法(貌似可以写theme解决,回头再实验下),如果有知道的,请告知,谢谢。

Presenter层

在ZhihuPresenterImp1类里实现数据和视图的绑定

  • 先写一个回调接口:
    (在Presenter层实现,给Model层回调,更改View层的状态,确保Model层不直接操作View层)
    presenter.OnZhihuDetailListener :
public interface OnZhihuDetailListener {    void onLoadZhihuDetailSuccess(ZhihuDetail zhihuDetail);    void onLoadDataError(String error);}
  • 再写一个presenter接口:
    presenter.ZhihuDetailPresenter :
public interface ZhihuDetailPresenter {    void getDetail(String id);}
  • 最后写Prestener实现类:
    presenter.imp1.ZhihuDetailPresenterImp1 .class:
public class ZhihuDetailPresenterImp1 extends BasePresenter implements ZhihuDetailPresenter,OnZhihuDetailListener{    /*Presenter作为中间层,持有View和Model的引用*/    private ZhihuDetailView mZhihuDetailView;    private ZhihuDetailModelImp1 zhihuDetailModelImp1;    String id;    public ZhihuDetailPresenterImp1(ZhihuDetailView zhihuDetailView) {        mZhihuDetailView = zhihuDetailView;        zhihuDetailModelImp1 = new ZhihuDetailModelImp1();    }    @Override    public void getDetail(String id) {        mZhihuDetailView.onStartGetData();        zhihuDetailModelImp1.loadDetail(id, this);    }    @Override    public void onLoadZhihuDetailSuccess(ZhihuDetail zhihuDetail) {        mZhihuDetailView.onGetDetailSuccess(zhihuDetail);    }    @Override    public void onLoadDataError(String error) {        mZhihuDetailView.onGetDetailFailed(error);    }}

更多相关文章

  1. 在Android库中不能使用switch-case语句访问资源ID
  2. Android开发 Handler+ExecutorService(线程池)+MessageQueue模式
  3. Android传感器的运用之ACCELEROMETER
  4. 什么是aidl?Android(安卓)AIDL详解
  5. 漫谈Android数据缓存、数据序列化和Intent传递复杂数据
  6. android camera API1调用camera HAL3流程学习总结
  7. Android学习笔记--Binder
  8. Android关机流程解析---从reboot说起
  9. Android和IOS获取crash信息

随机推荐

  1. 关于Android的问号?和@符号的用法
  2. AndroidManifest.xml android:name(应用中
  3. Google手机Android操作系统面试题
  4. Android(安卓)Https相关完全解析 当OkHtt
  5. Android View(一)
  6. 走马灯效果总结
  7. adb install将app安装到eclipse Android
  8. Android底部导航栏+消息提醒
  9. Android 开源动画框架:NineOldAndroids
  10. Android 数据存储之SharedPreferences存