我创建了以下类:
public class AsyncHttpsClientHelper {
public static final int REMOVE_CREDIT_CARD = 1;
public static final int ENABLE_AUTORENEW = 2;
// +10 final ints...
private static AsyncHttpsClientHelper instance = null;
private static Activity activity;
// Some other variables
private AsyncHttpsClientHelper(Context context) {
// Initiate variables
}
public static AsyncHttpsClientHelper getInstance(Context context) {
// Guarantees the same instance for this class (Singleton)
}
public void performNetworkTask(int networkTaskType, String value)
{
switch (networkTaskType)
{
case REMOVE_CREDIT_CARD:
{
CupsLog.d(TAG, "path: " + Consts.ACCOUNT_REMOVE_CREDIT_CARD_PATH);
client.post(Consts.ACCOUNT_REMOVE_CREDIT_CARD_PATH , new JsonHttpResponseHandler() {
@Override
public void onSuccess(JSONObject result) {
try {
CupsLog.d(TAG, Consts.ACCOUNT_REMOVE_CREDIT_CARD_PATH + " -> onSuccess, result: " + result.toString(3));
AccountService.getInstance(activity).pullAccountDetailsFromServer();
Toast.makeText(activity, "Your credit card was removed", Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Throwable arg0) {
CupsLog.d(TAG, "commitPaymentToServer -> onFailure");
BusProvider.getInstance().post(new DialogChangeEvent(DialogChangeEvent.REMOVE_CREDIT_CARD, "failed"));
}
});
break;
}
case ENABLE_AUTORENEW:
{
// Do ENABLE_AUTORENEW logic
}
// +10 cases goes here...
}
}
}
这个类还没有完成,我还要在这里添加另外10个我在应用程序周围执行的其他网络调用。
要运行其中一个网络任务,我运行此行,例如:
AsyncHttpsClientHelper.getInstance(this).performNetworkTask(AsyncHttpsClientHelper.COMMIT_COUPON_TO_SERVER, event.getValue());
任务完成后,我使用Event
事件Square
工具触发Bus
,以便为活动/片段布局提交所需的视觉更改。
问题:我的老板声称这是一种不好的做法,当我完成它时,这个课程会变得一团糟。更多的是他声称这个类应该是一个愚蠢的类,所有他知道如何做的是配置AsyncHttpClient
对象并将其返回,以便我可以使用它并执行相关Activity
内的https任务。基本上他说https调用本身应该位于Activity类中。我更喜欢这种方式,并认为它使我的活动更清洁,更好阅读。另一方面,他说这种方式更难以调试,而且这个类结合了Controller和View功能的一部分,它不应该这样做。
那么谁是对的?创建像这样的课真的是一种不好的做法吗?
答案 0 :(得分:4)
请参阅Google IO 2010关于Android REST客户端应用的演示文稿 - 我认为它是您问题的完整答案。
https://www.youtube.com/watch?v=xHXn3Kg2IQE
干杯:)
答案 1 :(得分:3)
你保持对你的活动的静态引用 - 这是不好的做法!如果在长时间运行的网络运行期间手机旋转怎么办?
Google I / O演示文稿中描述的最强大,最干净的解决方案。
您的解决方案有一些缺点:
根据您的问题 - 是的,调用AsyncHttpClient将导致您建议使用更清晰的代码。
答案 2 :(得分:1)
考虑Dimitry关于轮换的内容,因为它是真的。切勿对与UI有任何连接的对象使用静态引用。它会导致内存泄漏,并且很难调试。
其他问题:
并回答您的问题:
我的老板声称这是一种不好的做法,而且这个班级会 当我完成它时会变得一团糟。
是的,它会变得一团糟(当你开始添加/修改功能时会变得更糟)。
更多的是他声称这个班级应该是一个愚蠢的班级 所有他知道如何做的是配置AsyncHttpClient对象和 返回它,以便我可以使用它并在内部执行https任务 相关活动。
应该是愚蠢的。在我看来,你可以保留performNetworkTask方法,但是你需要有回调参数来让调用者做出不同的反应。
public void performNetworkTask(Request request, JsonHttpResponseHandler handler);
您还应该放弃int networkTaskType
。我的建议是使用抽象的Request类。但是,如果你喜欢这种方式,那么切换到Enum是最低限度的。
基本上他说https调用本身应该位于 活动类。
" Https来电"可以意味着什么。我认为他的意思是回调应该由调用者传递。
我更喜欢这种方式,并认为它使我的活动更清洁 并且更好阅读。
这样你在Activity中的代码肯定会少,但是你只能支持一个Activity!基本上,您只是将缺少的代码从Activity移动到此帮助程序类。更不用说以任何方式修改助手都会很痛苦。
另一方面,他说这种方式更难 调试,这个类结合了Controller和View的一部分 它不应该做的功能。那么谁是对的?它真的是一个 创建像这样的类的不良做法?
答案 3 :(得分:0)
使代码更易读,更易于维护是一种很好的做法。封装责任是两者兼顾的最佳方式之一。
对你的老板来说,一个很好的论据是:View中的View和服务器 STARTS 之间的连接以及服务器中的 END ,但获得它的人之间的联系完成(并且 RESPONSABLE )就是这个类。与Activity
或服务器如何完成无关,只有结果。
根据您所分享的代码进行一些修改,我建议:
getInstance()
initiator()
方法并启动AsyncHttpClient
,Gson
和其他参数performNetworkTask()
(他们可以并且也应该具有他们特定的方法名称)performNetworkTask()
会是这样的:
public class HttpsClientAsyncHelper {
Acitivity activity;
AsyncHttpClient client;
Gson gson;
// Other params
public static void initiator(Context context)
{
activity = (Activity) context;
client = new AsyncHttpClient().setCookieStore(CookieUtil.getInstance(activity)
.getPersistentCookieStore());
gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create();
}
// Other methods
}
再创建10个类:
public class RemoveCreditCardAsyncTask extends HttpsClientAsyncHelper {
public static void performNetworkTask(Context context)
{
initiator();
// Do what you did in this specific case
}
}
<强>用法:强>
RemoveCreditCardAsyncTask.performNetworkTask(this);
// specific method names
AutoRenewAsyncTask.enableAutoRenew(this);
AutoRenewAsyncTask.disableAutoRenew(this);
// even more specific
AutoRenewAsyncTask.enable(this);
AutoRenewAsyncTask.disable(this);
我自己在一个名为Network
的更通用的类中练习,它处理与WebService
的所有通信:
serverPostRequest(String controller, String action, JSONObject jsonParameters) throws Exception {}
fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {}
奖金:对您来说可能很有用的方法:
public static boolean isAvailable(Context context)
{
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
答案 4 :(得分:0)
也许来自Misko Hevery的链接:
http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/
及其后续行动:
http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/
会有所帮助。他专门处理信用卡应用程序中的单身人士,并且它具有隐含的MVC。 MVC无处不在。你通常需要一个很好的理由离开它。
你的逻辑中也有一个大的开关()。通常由OO中的多态性处理。方法擅长以单元测试友好的方式封装功能。
答案 5 :(得分:0)
我完全同意你的老板关于他说,这应该是一个愚蠢的阶级。而不是Helper类,您很可能需要一个类的 Executor 或 Worker 类。单身人士大部分时间都是邪恶的,毕竟你最终也会泄露你的背景并最终导致内存泄漏。
有一种更好的方法,使用自我保留Fragments
。
现在考虑一下,将你的助手类变成一个自我保留的Fragment
,它应该是系统的连接持有者,并且应该能够通过该连接执行某些任务。同样丢失switch...case
并将您的任务变成某类Runnable
或Callable
类。
现在你有一个基于片段的执行器,类和一堆可以执行的任务。这种方法将为您带来这些优势:
顺便说一句,您也可以使用Service
来代替Fragments,原则相同,但可能会更难实现,因为Service-Activity通信会增加另一层复杂性。
答案 6 :(得分:0)
尝试使用此方法进行与网络相关的任务:
1。创建HttpHelper
类,其中初始化http对象并编写帮助程序方法以执行http请求。
2。为您的所有http请求创建单独的AsyncTask
,并从此类初始化HttpHelper并执行网络操作,这有两个好处:
a)您的代码仍然可读且模块化,易于维护和调试。
b)由于网络请求是独立的,因此可以自由地在应用程序内的任何位置使用此类。
3。从AsyncTask Interface回传,可以使用Handler,也可以直接传递活动对象,但这样可以泄露上下文这可能导致内存泄漏。
答案 7 :(得分:0)
回答以下问题: