{"id":26845000,"url":"https://github.com/chinalwb/modularized_wan_android","last_synced_at":"2025-07-11T16:39:52.006Z","repository":{"id":112077781,"uuid":"162716107","full_name":"chinalwb/modularized_wan_android","owner":"chinalwb","description":"用玩Android学习android - 组件化 - and more.. (Retrofit + MVP + 组件化的玩Android)","archived":false,"fork":false,"pushed_at":"2019-01-16T10:04:39.000Z","size":2974,"stargazers_count":16,"open_issues_count":2,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-30T20:24:59.261Z","etag":null,"topics":["component","modularization","zu-jian-hua"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chinalwb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-21T13:15:43.000Z","updated_at":"2020-05-04T08:23:05.000Z","dependencies_parsed_at":null,"dependency_job_id":"ece876bb-4500-4251-9a2a-b573ed7b1225","html_url":"https://github.com/chinalwb/modularized_wan_android","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chinalwb/modularized_wan_android","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinalwb%2Fmodularized_wan_android","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinalwb%2Fmodularized_wan_android/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinalwb%2Fmodularized_wan_android/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinalwb%2Fmodularized_wan_android/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chinalwb","download_url":"https://codeload.github.com/chinalwb/modularized_wan_android/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinalwb%2Fmodularized_wan_android/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264853316,"owners_count":23673608,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["component","modularization","zu-jian-hua"],"created_at":"2025-03-30T19:34:06.671Z","updated_at":"2025-07-11T16:39:51.977Z","avatar_url":"https://github.com/chinalwb.png","language":"Java","readme":"# 组件化的 wan_android App\n\n* [前言](#前言)\n* [组件化思想](#组件化思想)\n* [实现方法](#实现方法)\n* [自己亲手做一个组件?](#自己亲手做一个组件)\n\n\n### 前言\n* 依照 玩Android 惯例，感谢鸿洋大神提供的 玩Android API\n* 我是一个小小小小小菜鸟，这个项目是我用来学习Android开发的\n* 最近听说组件化开发很流行，我感觉很神秘，于是在读过很少的一些资料之后开始按照自己的理解来做组件化的实现\n* 这个项目用“模块化”来表述更贴切\n* 对于组件化这个话题来说，我希望能用最简单的语言和实现来描述清楚我的理解。\n* 这个项目是从0x0000开始写的, 所以（我期望）像我一样的小白也能看的清清楚楚\n* 按照[自己亲手做一个组件?](#自己亲手做一个组件)检出代码, 自己练习一下就更明白他有多简单了\n* 这个项目中的东西极其简单，组件化的内容现在也是只是涵盖了我认为最主要的一部分，不过我会继续加强，引入更多有意思的东西\n* 希望路过的大神不吝赐教\n* 如果你也在学习组件化，不妨一起来做一个组件化实现 （我会在下面列出操作步骤），然后欢迎探讨、敬请不吝赐教\n\n### 组件化思想\n* 听起来很神秘，我现在很肤浅地理解为：把一个大的App进行拆分，每个功能或每个组件分别用一个 Android Library 或 Module 来实现。\n* 我很肤浅的理解为：其中最重要的一点是：如何拆分 以及 如何整合\n* 我很肤浅的在这个玩android app中做了一个简单的实现，大致如下：\n![结构图](./images/constructure.png)\n\n运行截屏：\n![导航](./images/nav.png)\n\n![首页](./images/main.png)\n\n![项目](./images/projects.png)\n\n![公众号](./images/gzh.png)\n\n![贡献者](./images/contributor.png)\n\n\nAndroid Studio截屏：\n![Android Studio](./images/as.png)\n\n### 实现方法\n1. 根据依赖关系的结构图，我把app分成了总分总的结构\n2. App是入口组件，依赖所有导航页的组件\n3. Base是基础组件，（不出意外的话）所有组件都依赖他\n4. 根据上面 NavigationView 的运行截图，我把每个导航项目都单独分成了一个组件，比如我已经实现的组件有：`wanandroid_projects` / `wanandroid_gzh` / `wanandroid_contributor`\n5. `wanandroid_base`中定义了一个 `BaseApplication`， 在这个类中有一个抽象方法 `public abstract void initServiceData();`, 所有导航页组件都继承此类并实现自己的 `initServiceData()` 方法，在这个方法内部提供导航控件所需要的信息\n6. 拿 `wanandroid_projects` 来说：他的代码为(`NavigationViewItem` 和 `ContributorItem` 是在base组件中定义的model)：\n```\npublic class ProjectApplication extends BaseApplication {\n\n    @Override\n    public void initServiceData() {\n        List\u003cNavigationViewItem\u003e navigationItemList = ServiceProvider.getNavigationViewService().getNavigationViewItemList();\n        NavigationViewItem navigationViewItem = new NavigationViewItem(\n                1,\n                R.id.nav_projects,\n                2,\n                \"项目\"\n        );\n\n        ProjectsFragment projectsFragment = ProjectsFragment.getInstance();\n        IProjectsApi projectsApi = RetrofitClient.getRetrofit().create(IProjectsApi.class);\n        new ProjectsPresenter(projectsApi, projectsFragment);\n        navigationViewItem.setFragment(projectsFragment);\n\n        navigationItemList.add(navigationViewItem);\n\n\n        // 初始化 贡献者 数据\n        ContributorService contributorService = ServiceProvider.getContributorService();\n        List\u003cContributorItem\u003e contributorItemList  = contributorService.getContributorItemList();\n        ContributorItem contributorItem = new ContributorItem(\n                \"https://avatars0.githubusercontent.com/u/1758864?s=460\u0026v=4\",\n                \"chinalwb\",\n                \"项目组件\",\n                \"项目组件为主组件提供了ProjectsFragment作为导航项目入口，Fragment内部使用MVP结构。\" +\n                        \"用Glide来显示RecyclerView#Adapter中的图片。\",\n                \"https://github.com/chinalwb\"\n        );\n        contributorItemList.add(contributorItem);\n    }\n}\n```\n7. `app`在运行的时候用反射读取所有导航页组件提供的信息并展示到页面上\n8. 由于每个导航页组件在初始化`NavigationViewItem `的时候都提供了Fragment，所以App运行的时候可以知道点击导航项之后显示哪个fragment\n\n### 自己亲手做一个组件 \n\n在上述内容基础上，如何实现一个自己的玩Android组件？\n1. checkout 这个项目\n2. 在Android Studio中，右键 `app`, 选择 `New Module` \u003e `Android Library` \u003e Next 填入：`wanandroid_test` \u003e Finish\n![New Module](./images/newModule.png)\n![New Module](./images/newModule2.png)\n3. 编辑 `wanandroid_test`项目下的`build.gradle`, 添加如下的dependencies配置：\n```\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n\n    implementation 'androidx.appcompat:appcompat:1.0.0-alpha1'\n    testImplementation 'junit:junit:4.12'\n    androidTestImplementation 'androidx.test:runner:1.1.0-alpha3'\n    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha3'\n\n\t // 以下为添加内容：\n    implementation project(':wanandroid_base')\n    commonDependencies.each { key, value -\u003e\n        if (key.endsWith('Anno')) {\n            annotationProcessor value\n        } else if (key.endsWith('Impl')) {\n            implementation value\n        } else if (key.endsWith('Api')) {\n            api value\n        }\n    }\n}\n```\n这一步有两个作用：一个是依赖base组件，另一个是对这个library加上全局的依赖. Sync 一下。\n\n4. 编辑 `app` 项目下的 `build.gradle`, 在dependencies部分加上对 `wanandroid_test` 的依赖\n```\nimplementation project(':wanandroid_test')\n```\nSync 一下。\n\n5. 在 `wanandroid_base` 项目中 res \u003e values \u003e ids.xml 中增加 `\u003citem name=\"nav_test\" type=\"id\"/\u003e`\n6. 在 `wanandroid_test` 项目中新建一个java类, 代码如下：\n\n```\npackage com.chinalwb.wanandroid_test;\n\nimport com.chinalwb.wanandroid_base.BaseApplication;\nimport com.chinalwb.wanandroid_base.ServiceProvider;\nimport com.chinalwb.wanandroid_base.services.contributor.ContributorItem;\nimport com.chinalwb.wanandroid_base.services.contributor.ContributorService;\nimport com.chinalwb.wanandroid_base.services.navigation.NavigationViewItem;\nimport com.chinalwb.wanandroid_base.services.navigation.NavigationViewService;\n\nimport java.util.List;\n\npublic class TestApplication extends BaseApplication {\n    @Override\n    public void initServiceData() {\n        // 初始化 导航 数据\n        NavigationViewService navigationViewService = ServiceProvider.getNavigationViewService();\n        List\u003cNavigationViewItem\u003e navigationViewItemList = navigationViewService.getNavigationViewItemList();\n\n        NavigationViewItem navigationViewItem = new NavigationViewItem(\n                1,\n                R.id.nav_test,\n                99,\n                \"测试组件\"\n        );\n        TestFragment testFragment = TestFragment.newInstance();\n        navigationViewItem.setFragment(testFragment);\n        navigationViewItemList.add(navigationViewItem);\n\n        // 初始化 贡献者 数据\n        ContributorService contributorService = ServiceProvider.getContributorService();\n        List\u003cContributorItem\u003e contributorItemList = contributorService.getContributorItemList();\n        ContributorItem contributorItem = new ContributorItem(\n                \"http://www.wanandroid.com/resources/image/pc/logo.png\",\n                \"你的名字\",\n                \"测试组件\",\n                \"这是一个测试组件！写完提PR哦！\",\n                \"你的网址\"\n        );\n        contributorItemList.add(contributorItem);\n    }\n}\n\n```\n\n你会发现 TestFragment 提示错误，因为还没创建，我们马上创建一个。\n\n7. 创建一个TestFragment，代码如下：\n\n```\npackage com.chinalwb.wanandroid_test;\n\nimport android.os.Bundle;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.fragment.app.Fragment;\n\npublic class TestFragment extends Fragment {\n\n    public TestFragment() {\n\n    }\n\n    public static TestFragment newInstance() {\n        return new TestFragment();\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View view = inflater.inflate(R.layout.test_fragment, container, false);\n        return view;\n    }\n}\n\n```\n\nlayout (你需要自己创建一个 layout 文件夹):\n\n```\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cLinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\" android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\u003e\n\n    \u003cTextView\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n\n        android:text=\"这是我的测试组件！\"\n        android:textSize=\"20sp\"\n        /\u003e\n\u003c/LinearLayout\u003e\n```\n\n8. 把这个组件在 base 组件的 `AppConfig.java` 中注册一下，这样，app启动的时候就会加载他。\n\n```\npackage com.chinalwb.wanandroid_base;\n\npublic class AppConfig {\n\n    private static final String MODULE_PROJECT = \"com.chinalwb.wanandroid_projects.ProjectApplication\";\n    private static final String MODULE_TREE = \"com.chinalwb.wanandroid_tree.TreeApplication\";\n    private static final String MODULE_GZH = \"com.chinalwb.wanandroid_gzh.GzhApplication\";\n    private static final String MODULE_CONTRIBUTOR = \"com.chinalwb.wanandroid_contributor.ContributorApplication\";\n    private static final String MODULE_TEST = \"com.chinalwb.wanandroid_test.TestApplication\";\n\n    public static String[] MODULES = {\n            MODULE_PROJECT,\n            MODULE_TREE,\n            MODULE_GZH,\n            MODULE_CONTRIBUTOR,\n            MODULE_TEST\n    };\n\n}\n```\n\n9. 运行!\n\n\n导航页加了一项:\n![测试组件](./images/test.png)\n\n点击显示TestFragment:\n![TestFragment](./images/test2.png)\n\n贡献者列表中也加上了你的名字:\n![贡献者列表](./images/test3.png)\n\n\n10. 我知道其中有很多可以改进的地方，请您指出来吧！\n\n\n\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchinalwb%2Fmodularized_wan_android","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchinalwb%2Fmodularized_wan_android","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchinalwb%2Fmodularized_wan_android/lists"}