最近在和小伙伴一起维护一个github项目,https://github.com/Moosphan/Android-Daily-Interview。
每天出一道面试题。感兴趣的可以点进去看看。最近要开始整理答案。所以顺手也在这里发布下自己写的相关面试题的答案。
原题链接
以下是正文。
开始介绍方法之前,先借用之前lx36301766 写的答案里的一句话,我个人觉得写的很到位:
说到底就是两个普通的JAVA对象相互都持有对方的引用,直接回调就成,哪还需要什么别的通信方式,很简单的问题别搞复杂了
大家都知道java是面向对象的编程语言。只要拿到对象,想做什么操作其实很简单。好开始正文。
从两个方面开始说
- Activity与Fragment通信
- Fragemnt与Activity通信
1 Activity与Fragment通信
1.1 广播
这个就不写,相信大家都会
1.2 对象调用public方法
public class TestActivity extends AppCompatActivity{
private TestFragmet testFragment;
public void test(){
testFragment = new TestFragmet();
testFragment.doTest();
}
}
public class TestFragmet extends Fragmenyt{
private TestActivity activity;
public void doTest(){
Log.d(TAG,"收到消息");
}
}
1.3 接口
public class TestActivity extends Activity{
private ITest iTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
iTest = new TestFragment();
iTest.doTest();
}
}
public class TestFragment extends Fragment implements ITest{
@Override
public void doTest() {
Log.i(TAG, "doTest: ");
}
}
public interface ITest{
void doTest();
}
1.4 观察者
这里模拟一个场景,用户在activity里登录状态发生了改变,fragment展示退出登录的UI。我真实项目里也是采用的观察者模式管理登录状态,因为登录状态的改变牵连到一系列的改变。
public class TestActivity extends Activity {
final int LOGIN_OUT = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LoginManager.loginStatusChanged(LOGIN_OUT);
}
}
public class TestFragment extends Fragment implements LoginObserver {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
/**
* 订阅事件
*/
LoginManager.registerLoginObserver(this);
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onDestroy() {
super.onDestroy();
/**
* 反订阅事件
*/
LoginManager.unregisterLoginObserver(this);
}
@Override
public void loginStatusChange(int status) {
Log.i(TAG, "loginStatusChange: "+status);
}
}
public class LoginManager {
private static ArrayList<LoginObserver> loginObserverList = new ArrayList<>();
public static void registerLoginObserver(LoginObserver loginObserver){
loginObserverList.add(loginObserver);
}
public static void unregisterLoginObserver(LoginObserver loginObserver){
loginObserverList.remove(loginObserver);
}
public static void loginStatusChanged(int loginstatus){
for (LoginObserver observer:loginObserverList){
if (observer!=null){
observer.loginStatusChange(loginstatus);
}
}
}
}
public interface LoginObserver{
void loginStatusChange(int status);
}
1.5 eventbus
也没什么好说的,相信大家都用过
2 Fragemnt与Activity通信
2.1 广播
同1.1
2.2 对象调用public方法
public class TestActivity extends Activity {
public void doTest(){
Log.i(TAG, "doTest: ");
}
}
public class TestFragment extends Fragment {
private TestActivity activity;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (getActivity() instanceof TestActivity){
activity = getActivity();
}
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
void test(){
activity.doTest();
}
}
2.3 接口
public class TestActivity extends Activity implements ITest{
@Override
public void doTest() {
Log.i(TAG, "doTest: ");
}
}
public class TestFragment extends Fragment {
private ITest iTest;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof ITest){
iTest = (ITest) context;
}
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
void test(){
iTest.doTest();
}
}
public interface ITest{
void doTest();
}
2.4 观察者
同1.4,只不过这次是fragmnet改变用户登录状态,activiy观察事件而已。
public class TestActivity extends Activity implements LoginObserver {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LoginManager.registerLoginObserver(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
LoginManager.unregisterLoginObserver(this);
}
@Override
public void loginStatusChange(int status) {
}
}
public class TestFragment extends Fragment {
final int LOGIN_OUT = 0;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
void doTest(){
LoginManager.loginStatusChanged(LOGIN_OUT);
}
}
public class LoginManager {
private static ArrayList<LoginObserver> loginObserverList = new ArrayList<>();
public static void registerLoginObserver(LoginObserver loginObserver){
loginObserverList.add(loginObserver);
}
public static void unregisterLoginObserver(LoginObserver loginObserver){
loginObserverList.remove(loginObserver);
}
public static void loginStatusChanged(int loginstatus){
for (LoginObserver observer:loginObserverList){
if (observer!=null){
observer.loginStatusChange(loginstatus);
}
}
}
}
public interface LoginObserver{
void loginStatusChange(int status);
}
2.5 eventbus
自行百度吧,这个很简单。
题外话
大家可能发现接口和对象调用public方法出奇的相似,那么为什么要多次一举写个接口呢?大家可以点击一下TestFragment#test() 里的iTest.doTest();会发现跳转到了ITest接口里,而点击TestFragment#test()里的activity.doTest();确实跳转到了TestActivity里。到这里相信大家就看出接口的一个妙用,隐藏实现,当然不是完全隐藏,你可以通过搜索哪里实现继续查看。当然接口还有其他功能,就不赘述了。