待优化的代码见上个博客:https://blog.youkuaiyun.com/wangning13ji/article/details/85064184
本文针对Test4里的MainActivity进行优化。
优化前:MainActivity.java
package com.test4.w00425655.test4;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final TextView mTextview = (TextView) findViewById(R.id.textview);
try {
//获取UID,验证是否相同
PackageManager pm = getPackageManager();
ApplicationInfo ai = pm.getApplicationInfo("com.test4.w00425655.test4", 0);
Toast.makeText(MainActivity.this, Integer.toString(ai.uid,10), Toast.LENGTH_SHORT).show();
mTextview.setText(Integer.toString(ai.uid,10));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Context context = null;
try {
context = this.createPackageContext("com.test5.w00425655.test5",CONTEXT_INCLUDE_CODE|Context.CONTEXT_IGNORE_SECURITY);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
final Context finalContext = context;
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Class clazz = null;
Object object = null;
try {
//加载Test4的类和函数
clazz = finalContext.getClassLoader().loadClass("com.test5.w00425655.test5.MainActivity");
object = clazz.newInstance();
Method method = clazz.getDeclaredMethod("getString",String.class);
mTextview.setText((String)method.invoke(object,"cccccccccc"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
各位看官可以看到,优化前该Activity毫无设计模式和原则可言,是不是闻到了代码腐朽的味道,看到这样的代码是不是没有了继续写下去的勇气啦。没关系,接下来,我们将对它进行一次人生的洗礼,让它的价值得到完美的升华。
我们会利用单一职责原则,把加载类和调用方法的函数抽离出来封装一个类,该类只负责动态加载类,不进行其他操作。接着还需要利用接口隔离原则,把该类抽象成一个接口,这样,我们暴露给调用者的只有接口,不会有具体的实现,看起来是不是更加清晰明了了呢。最后,这个类我们只需要一个单例,不需要每次调用的时候都创建一个对象,节省了资源。下面就来看看最终的实现吧!duang~
抽象的接口类LoadClassService.java
package com.test4.w00425655.test4;
import android.content.Context;
public interface LoadClassService {
/*Test5提供给Test4的接口*/
String getString(String str, Context context);
}
接口的实现LoadClassImpl.java
package com.test4.w00425655.test4;
import android.content.Context;
import android.content.pm.PackageManager;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static android.content.Context.CONTEXT_INCLUDE_CODE;
public class LoadClassImpl implements LoadClassService {
private volatile static LoadClassService sLoadClass = null;
private LoadClassImpl (){
};
public static LoadClassService getLoadClass (){
if (null == sLoadClass) {
synchronized (LoadClassImpl.class) {
if (null == sLoadClass) {
sLoadClass = new LoadClassImpl();
}
}
}
return sLoadClass;
}
@Override
public String getString (String str,Context context) {
Class clazz = null;
Object object = null;
try {
//加载Test4的类和函数
clazz = getClazz("com.test5.w00425655.test5","com.test5.w00425655.test5.MainActivity",context);
object = clazz.newInstance();
Method method = clazz.getDeclaredMethod("getString",String.class);
return (String)method.invoke(object,str);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
private Class getClazz(String path, String className,Context context){
Class clazz = null;
try {
//加载Test4的类
clazz = context.getClassLoader().loadClass(className);
return clazz;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
MainActivity.java的调用:
package com.test4.w00425655.test4;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final TextView mTextview = (TextView) findViewById(R.id.textview);
try {
//获取UID,验证是否相同
PackageManager pm = getPackageManager();
ApplicationInfo ai = pm.getApplicationInfo("com.test4.w00425655.test4", 0);
Toast.makeText(MainActivity.this, Integer.toString(ai.uid,10), Toast.LENGTH_SHORT).show();
mTextview.setText(Integer.toString(ai.uid,10));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Context context = null;
try {
context = this.createPackageContext("com.test5.w00425655.test5",CONTEXT_INCLUDE_CODE|Context.CONTEXT_IGNORE_SECURITY);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
final Context finalContext = context;
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LoadClassService loadClass = LoadClassImpl.getLoadClass();
mTextview.setText(loadClass.getString("cccc", finalContext));
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
这样我们的优化就这么简单的完成了,是不是更加清晰明了了呢。真棒~