待優化的代碼見上個部落格:https://blog.csdn.net/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);
}
}
這樣我們的優化就這麼簡單的完成了,是不是更加清晰明了了呢。真棒~