美文网首页
ViewPager+Fragment懒加载

ViewPager+Fragment懒加载

作者: 大鹏的鹏 | 来源:发表于2017-10-17 10:56 被阅读12次

<main class="container" style="display: block; margin: 2em 10px; color: rgb(52, 73, 94); font-family: sourcesanspro, "Helvetica Neue", Arial, sans-serif; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);">

<article class="post-block" style="display: block;">

Android反编译工具总结

2017年3月19日

最近想写自己写个apk,但是苦于没有本人不会ui、不会ps(那我会啥 ╮(╯▽╰)╭),就会敲代码,so 就反编译了下我感觉ui好看的apk,反编译了这么多个apk希望不要被抓到(::>_<::)……

<a id="more" style="background-color: transparent; color: rgb(66, 185, 131); text-decoration: none; word-break: break-all;"></a>

首先来简单的说明下Apk文件本质上其实是一个zip包。我们直接进行解压就能看到其中的目录。

Android反编译工具总结

目录说明

  • AndroidManifest.xml:应用的全局配置文件
  • classes.dex:源代码编译成class后,转成jar,再压缩成dex文件,dex是可以直接在Android虚拟机上运行的文件。
  • lib文件夹:引用的第三方sdk的so文件。
  • META-INF文件夹:Apk签名文件。
  • res文件夹:资源文件,包括了布局、图片等等。
  • resources.arsc:记录资源文件和资源id的映射关系。
  • 其中还有一个没有显示就是→assets文件夹:原始资源文件夹,对应着Android工程的assets文件夹,一般用于存放原始的网页、音频等等。

上述的这些说明 简单的说明了一个apk基本包含的东西,直接把apk解压是没有办法进行阅读的,在打包这个过程中经过了build-tools处理了。

其实反编译Apk的目的就是Apk拆成我们可以阅读的文件。通过反编译,我们一般想要得到里面的AndroidManifest.xml文件、res文件和java代码。

我将介绍3个工具来对apk进行反编译

1.利用ApkTool,获取AndroidManifest和res等资源文件

怎么得到Apk下的资源文件,这是个问题,我上网查找是发现了ApkTool工具,当时给我的感觉就好像是发现新大陆一样

工具地址:

https://ibotpeaches.github.io/Apktool/

功能:拆解Apk文件,反编译其中的资源文件,将它们反编译为可阅读的AndroidManifest.xml文件和res文件。因为直接把Apk文件当做zip解压,得到的xml资源文件,都是无法直接用文本编辑器打开阅读的,因为它们在打包时经过了build-tools的处理。

安装:

https://ibotpeaches.github.io/Apktool/install/

最新版本是2.2 需要的环境是jdk 1.7以上

  • 下载apktool-2(最新
  • 将下载的jar重命名为
`apktool.jar`
  • 将这两个文件(apktool.jarapktool.bat)移动到您的Windows目录(通常C://Windows
  • 如果没有访问权限C://Windows,可以将这两个文件放在任何位置,然后将该目录添加到您的环境变量系统PATH变量。
  • 尝试apktool通过命令提示符运行

下面我在win10 上演示如何利用ApkTool 进行反编译的

上述说到如果你把文件移动到其他的位置,就需要配置环境变量,上述有提到

首先进入到你想要 反编译的apk 目录下,我为了方便就放置到一起了。

Android反编译工具总结

我们可以从下图看到反编译出来的具体内容

Android反编译工具总结

我们已经得到一个可以用文本编辑器打开的阅读的AndroidManifest.xml文件、assets文件夹、res文件夹、smali文件夹等等。original文件夹是原始的AndroidManifest.xml文件,res文件夹是反编译出来的所有资源,smali文件夹是反编译出来的代码。这里smali 不做说明。

这时,我们已经可以文本编辑器打开AndroidManifest.xml文件和res下面的layout文件了。这样,我们就可以查看到这个Apk文件的package包名、Activity组件、程序所需要的权限、xml布局、图标等等信息。

其他用法 :https://ibotpeaches.github.io/Apktool/documentation/

<figure class="highlight java" style="display: block; margin: 1em 0px; position: relative; border-radius: 2px; line-height: 1.1em; background-color: rgb(248, 248, 248); overflow-x: auto; box-shadow: rgba(0, 0, 0, 0.121569) 0px 1px 2px;">

|

<pre style="overflow: auto; font-family: "Roboto Mono", Monaco, courier, monospace; font-size: 0.8em; background-color: rgb(248, 248, 248); color: rgb(82, 82, 82); padding: 1.2em 1.4em; line-height: 1.5em; margin: 0px;">

java -jar apktool.jar d test.apk

-f 如果目标文件夹已存在,强制删除现有文件夹

-o 指定反编译的目标文件夹的名称(默认会将文件输出到以Apk文件名命名的文件夹中)

-s 保留classes.dex文件(默认会将dex文件解码成smali文件)

-r 保留resources.arsc文件(默认会将resources.arsc解码成具体的资源文件)

// 注意apktool.jar是刚才下载后的jar的名称,d参数表示decode

// 在这个命令后面还可以添加像-o -s之类的参数,例如

// java -jar apktool.jar d yourApkFile.apk -o destiantionDir -s

// 几个主要的参数设置方法及其含义:

</pre>

|

</figure>

2.利用dex2jar反编译dex文件,得到java源代码

在上面说到我们通过apkTool反编译获得apk 等资源文件,如果你想获取源代码呢,怎么办,这时候就需要dex2jar登场了。

工具地址:

https://github.com/pxb1988/dex2jar

功能:将dex格式的文件,转换成jar文件。dex文件时Android虚拟机上面可以执行的文件,jar文件大家都是知道,其实就是java的class文件。在官网有详细介绍。

安装:

打开下载的文件进行解压后进入/dex2jar目录下,里面有脚本本件,进入终端后,输入命令就可以使用啦。

使用:

利用终端进入到你的dex2jar目录下,输入命令进行获取

Android反编译工具总结

这个时候就有人问我,你那个classes.dex是怎么获得的,其实在我最开始讲述的时候说过,把apk解压下来就能获得classes.dex文件,之后赋值到dex2jar目录下 ,执行命令。

这个时候又有人问我了(怎么这么多人问我),我怎么看生成的这个jar包呀。这个时候就需要 jd-gui了

2.1 jd-gui查看java源代码

工具下载地址:官网http://jd.benow.ca/上选择自己所需要的版本,github

用法:

下载完成后直接打开,把生成的classes-dex2jar.jar 文件直接拖到里面就可以观看了

[图片上传失败...(image-481c6b-1512011903725)]

3.jadx反编译Akp,得到.java源代码

介绍:

又双人问我有没有直接生成.java文件的,我说有啊,那就是是是是jadx

其中我在上网查找之前apktool+dex2jar+jd-gui一直是一个比较流行的Android反编译组合。

功能 :

但是jadx具有以下两个优点

  • 可以直接反编译出.java文件
  • 查看源码时直接显示资源名称,而不是像jd-gui里显示的资源ID

工具地址 :

  • github:
[https://github.com/skylot/jadx/releases](https://github.com/skylot/jadx/releases)
  • sourceforge:
[http://sourceforge.net/projects/jadx/files/](http://sourceforge.net/projects/jadx/files/)

安装:

下载完成后进行解压

使用:

进入bin目录下执行jadx-gui.bat,jadx也有GUI,进入后选中然将要反编译的apk即可,运行效果如下。

Android反编译工具总结

如果要保存源码,选择File->Save ALL即可保存文件,然后就可以导入Android Studio等IDE中。我们也可以直接使用命令行反编译apk文件:

<figure class="highlight" style="display: block; margin: 1em 0px; position: relative; border-radius: 2px; line-height: 1.1em; background-color: rgb(248, 248, 248); overflow-x: auto; box-shadow: rgba(0, 0, 0, 0.121569) 0px 1px 2px;">

|

<pre style="overflow: auto; font-family: "Roboto Mono", Monaco, courier, monospace; font-size: 0.8em; background-color: rgb(248, 248, 248); color: rgb(82, 82, 82); padding: 1.2em 1.4em; line-height: 1.5em; margin: 0px;">

jadx -d out classes.dex #直接输出.java文件到out目录

jadx-gui classes.dex #使用gui打开

</pre>

|

</figure>

现在你就可以用到jadx啦,不过获取资源等文件我还是建议使用ApkTool

4.ClassyShark谷歌亲儿子 你知道

工具地址:

https://github.com/google/android-classyshark/releases

功能:可直接浏览 Apk中的xml文件等,支持对.dex, .aar, .so,.apk, .jar, .class等文件的操作。

安装:

下载ClassyShark.jar后直接点击使用就可以了。

用法:

直接点击左上角打开你想要解析的apk就可以啦。

它可以直观的看到Apk 下每个包中的方法数,并且以直观的扇形图展示在右边。(这里面直接使用的是内涵段子的apk)

这个时候就可以看到apk 下用到的第三方框架啦

Android反编译工具总结

同时你可以直接看到所使用的 xml 文件等布局文件,同时你也可以看到apk下所包含的方法数是多少以及它使用的开源库等信息。

Android反编译工具总结 Android反编译工具总结

总结

其实还有有两个没有介绍到enjarify 、 Procyon 这个两个讲下之后进行更新

其实我们反编译apk,就是进行更多的学习,想看看其他apk的具体逻辑是怎么实现的,如果你想要只是简单的获得资源等文件只用apkTool就可以啦。

以上的几个工具给我的感觉还是不错的,基本可以实现我现在的需求(毕竟我只需要获得资源文件就好了)

参考

[那些值得你试试的Android竞品分析工具]

[Android反编译技术总结]

</article>

</main>

<footer style="display: block; padding-bottom: 1px; color: rgb(52, 73, 94); font-family: sourcesanspro, "Helvetica Neue", Arial, sans-serif; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);">

PREVNEXT

</footer>
ViewPager+Fragment的搭配在日常开发中也比较常见,可用于切换展示不同类别的页面,ViewPager控件有个特有的预加载机制,即默认情况下当前页面左右两侧的1个页面会被加载,以方便用户滑动切换到相邻的界面时,可以更加顺畅的显示出来.如果加载数据的操作都比较耗时或者都是类似图片的占用大量内存,这时就应该考虑想想是否该实现懒加载。也就是,当我打开哪个Fragment的时候,它才会去加载数据。

1.创建懒加载的LazyFragment .

public abstract class LazyFragment extends Fragment {
    // 标识view 是否初始化完成
    protected boolean isViewInit = false;
    // 当前Fragment 是否可见
    protected boolean isVisible = false;
    // 是否加载过数据
    protected boolean isLoadData = false;


    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        this.isVisible = isVisibleToUser;
        preLoadData(false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        this.isViewInit = true;
        // 防止一开始加载的时候未 调用 preLoadData 方法, 因为setUserVisibleHint 比 onActivityCreated 触发 前
        if (getUserVisibleHint()) {
            preLoadData(false);
        }
    }

    /**
     * 子类加载数据
     */
    protected abstract void loadData();

    /**
     * 当UI初始化成功,UI可见并且没有加载过数据的时候 加载数据
     *
     * @param forceLoad 强制加载数据
     */
    public void preLoadData(boolean forceLoad) {
        if (isViewInit && isVisible && (!isLoadData || forceLoad)) {
            loadData();
            isLoadData = true;
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        //当界面校会的时候将标识置空
        isViewInit = false;
        isVisible = false;
        isLoadData = false;
    }
}

2.创建子fragment集成LazyFragment 然后在loadData()函数里面进行数据加载的操作.

public class SubFragment extends LazyFragment {
    public static SubFragment getInstance(List<String> photos, String name) {
        SubFragment subFragment = new SubFragment();
        return subFragment;
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.d(TAG, mTagName + " onCreateView()");
        return inflater.inflate(R.layout.fragment_sub, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Log.d(TAG, mTagName + " onViewCreated()");
         ....//初始化界面
    }

    @Override
    protected void loadData() {
        Log.d(TAG, mTagName + " loaddata()");
        pullData();
    }

    /**
     * 模拟网络耗时操作拉取数据
     */
    private void pullData() {
       ...//加载数据
    }
}

相关文章

网友评论

      本文标题:ViewPager+Fragment懒加载

      本文链接:https://www.haomeiwen.com/subject/dbwruxtx.html