我的 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
参考文献:
我正在(第一次)编写一个 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
参考文献: