我的 Android 库中的包结构更好

Better packages structure in my Android library

我正在(第一次)编写一个 Android 库(有自己的活动),它将使用 Android aar 包导入到其他 Android 项目中。

我的目标是只发布一个 class(我们称它为 MyPlugin),它可以提供 public 方法的所有功能(调用活动等);但在我看来,所有活动都必须是 public;所以我想将用户想要使用的 classes 与我不想使用的 classes 分开。类似于:

com.mycompany.myplugin.api
 |--> MyPlugin (public class with public methods)
com.mycompany.myplugin.activities
 |--> Acitivty1
 |--> ....
 |--> ActivityN (public? activities)
com.mycompany.myplugin.mystuff
 |--> Services (protected? class with protected? methods)

通过这种设计,我可以对用户说 "You should use only api package"。

问题出在服务 class:它被 Activities 和 MyPlugin 使用,如果我希望它(或其方法)成为 protected(所以最终用户看不到它)。

我知道通过反射最终用户可以做任何事情,但我希望尽可能干净和简单。

我找到的唯一解决方案是只有一个包含所有 class 的程序包,但是,正如我所说,我想将 MyPlugin 与 Activities 分开。

您不能创建非 public Android 组件(Activity、服务、BroadcastReceiver)。他们的构造函数也不能是非public.

按功能而非组件填充包通常是个好主意:例如

|-awesomefeatureone
|----Activity1
|----Fragment1
|----AsyncTask1
|----Service1
|-awesomefeaturetwo
|----BroadcastReceiver2
|----Service2

在这种情况下,您可以使用一些有用的封装技巧(package-local 可见性,protected 东西)。

我想您将无法向最终用户隐藏您的组件 类。但是您可能会直接从客户端代码中禁止 运行 您的组件之一:使用评论中建议的方法@billmuell,或者只使用包本地附加功能来启动 Activity,包本地参数附加功能来创建 Fragment...你明白了。

public class SomeFragment extends Fragment{
    static final String ARG = "package_local_arg";
    protected void onCreate(Bundle state){
        super.onCreate(state);
        Bundle args = getArguments();
        if(args == null || !args.contains(ARG)){       
            throw new IllegalStateException();
        }
    }
}


public class SamePackageActivity extends Activity {

   public void doSometh(){
        Fragment f = new SomeFragment();
        Bundle args = new Bundle();
        args.putInt(SomeFragment.ARG, 1);
        f.setArguments();
        ...
   }
}

一个常见的约定是使用名为 internal 的包作为私有包 implementation/internal 类 .

com.mycompany.myplugin // all public stuff here and in its subpackages
com.mycompany.myplugin.internal // all non public stuff

此外,请遵循 建议:

It's often good idea to populate your package by feature, not by component

参考文献: