[英]Using Thread/Handler/Looper for Worker Thread Android
实施Thread / Handler / Looper意识形态以通过传递消息在后台处理信息时,存在一些响应性问题。 我真的不想使用AsyncTask类,因为我已经知道如何使用它来完成我想做的事情。
有人可以帮我使用以下代码,这些代码使用GooglePlayServicesUtil类下载Apache许可证,并在DialogFragment内的TextView中显示它吗?
我最大的问题是,当我启动它时,有时显示DialogFragment的速度很快,但另一些则非常慢。 我真的不知道,也许我没有遵循最佳实践来加载DialogFragment。
更新添加的代码现在可以正常工作,但是由于某种原因,我仍然会偶尔获得UI Freeze。 有人知道这是否特定于设备吗? 我目前正在使用三星GS3。 。 。
我的DialogFragment:
public class ApacheLicenseDialog extends DialogFragment implements Handler.Callback{
// Message Constants
private static final int MSG_DO_WORK = 0;
private static final int MSG_START = 1;
private static final int MSG_DONE = 2;
private static final int MSG_SHUTDOWN = 3;
// UI Elements
private TextView m_textApacheLicense = null;
private Button m_btnOk = null;
private ProgressBar m_apacheProgress = null;
// Background Processing Objects
private BackgroundThread m_bgThread = null;
protected Handler m_handler = null;
// Apache String Object
private String apacheLicense = null;
// ----------------------------------------------------------------------------
// New Instance Method invokes DialogFragment constructor
public static ApacheLicenseDialog newInstance(int counter)
{
// Create the Apache License Dialog
ApacheLicenseDialog dialog = new ApacheLicenseDialog();
Bundle data = new Bundle();
data.putInt("Counter", counter);
Log.d("COUNTER", "New Instance called: "+ Integer.toString(counter)+" times.");
// Set the Arguments for the Dialog
dialog.setArguments(data);
// Return the Dialog
return dialog;
}
// ---------------------------------------------------------------------------
// Class Overrides
/* (non-Javadoc)
* @see android.support.v4.app.DialogFragment#onCreate(android.os.Bundle)
*/
@Override public void onCreate(Bundle savedInstanceState)
{
// Perform the Default Behavior
super.onCreate(savedInstanceState);
setRetainInstance(true);
// Create a new Handler, Background thread, and Start the Thread
m_handler = new Handler(this);
m_bgThread = new BackgroundThread();
m_bgThread.start();
}
/*
* (non-Javadoc)
*
* @see
* android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater,
* android.view.ViewGroup, android.os.Bundle)
*/
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Set the Layout from XML Resource
return inflater.inflate(R.layout.apache_dialog_fragment, null);
}
/*
* (non-Javadoc)
*
* @see
* android.support.v4.app.DialogFragment#onActivityCreated(android.os.Bundle
* )
*/
@Override public void onActivityCreated(Bundle savedInstanceState)
{
// Perform Default Behavior
super.onActivityCreated(savedInstanceState);
// Reference this Dialog and Set its Title
getDialog().setTitle(getActivity().getResources().getString(R.string.text_Apache_License_Title));
// Reference the UI Elements
m_textApacheLicense = (TextView) getView().findViewById(R.id.textViewApacheLicense);
m_apacheProgress = (ProgressBar) getView().findViewById(R.id.apacheProgress);
m_btnOk = (Button) getView().findViewById(R.id.btnOkay);
// Add a Listener to the Button
m_btnOk.setOnClickListener(OkListener);
// Starts the Message Sending
init();
}
/* (non-Javadoc)
* @see android.support.v4.app.DialogFragment#onDismiss(android.content.DialogInterface)
*/
@Override public void onDismiss(DialogInterface dialog)
{
// Cleaned up this code, and Added some logging to test my message passing
m_bgThread.m_workerHandler.obtainMessage(MSG_SHUTDOWN).sendToTarget();
Log.d("DISMISSING", "Dismissed called on ApacheLicenseDialog");
try {
m_bgThread.join();
Log.d("JOINING_THREAD", "Attempting to join the Thread");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
Log.d("JOINED_THREAD", "Thread successfully joined");
}
// Perform the default behavior
super.onDismiss(dialog);
}
// ----------------------------------------------------------
// Handler.Callback Interface
@Override public boolean handleMessage(Message msg)
{
switch(msg.what)
{
case MSG_START:
// Set the ProgressBar View to Visible
m_apacheProgress.setVisibility(View.VISIBLE);
break;
case MSG_DONE:
updateUI(msg);
break;
}
// return true
return true;
}
// ---------------------------------------------------------------------------
// Private Class Method
private void init()
{
// Send the Message to this Classes Handler
m_bgThread.m_workerHandler.obtainMessage(MSG_DO_WORK).sendToTarget();
}
private void updateUI(Message msg)
{
// Set the ProgressBar View to Invisible
m_apacheProgress.setVisibility(View.INVISIBLE);
// Update the UI
m_textApacheLicense.setText(msg.obj.toString());
}
private void obtainApacheLicense()
{
// Send message that the operation is Starting
m_bgThread.m_workerHandler.obtainMessage(MSG_START).sendToTarget();
// Fetch the ApacheLicense
apacheLicense = GooglePlayServicesUtil.getOpenSourceSoftwareLicenseInfo(getActivity());
// Send Message the the operation is Done
m_handler.obtainMessage(MSG_DONE, apacheLicense).sendToTarget();
}
// ---------------------------------------------------------------------------
// Listeners
private OnClickListener OkListener = new OnClickListener()
{
@Override public void onClick(View v)
{
// Dismiss the Dialog
dismiss();
}
};
// ---------------------------------------------------------------------------
// BackgroundThread Class used to Fetch the Apache License from GooglePlayServicesUtil Class
private class BackgroundThread extends Thread implements Handler.Callback{
// Looper and Handler for the Background Thread
private Looper m_workerLooper;
protected Handler m_workerHandler;
@Override public void run()
{
// Do background Processing
Looper.prepare();
m_workerLooper = Looper.myLooper();
m_workerHandler = new Handler(m_workerLooper, BackgroundThread.this);
Looper.loop();
}
@Override public boolean handleMessage(Message msg)
{
switch(msg.what)
{
case MSG_DO_WORK:
// Run the obtainApacheLicenseFunction in this Thread
obtainApacheLicense();
break;
case MSG_SHUTDOWN:
// Clean up the Looper by calling quit() on it
m_workerLooper.quit();
Log.d("BACKGROUND_THREAD","Looper is shut down");
break;
}
// Return true
return true;
}
}
}
我通过使用switch语句来表明这一点:
// Runs the Apache Source Code in the Background
private void launchApacheDialogFragment(FragmentManager fm,FragmentTransaction ft)
{
counter++;
// Check if the Dialog Already Exists
m_dialogFragment = (ApacheLicenseDialog) fm.findFragmentByTag(APACHE_FRAGMENT);
if(m_dialogFragment != null)
{
ft.remove(m_dialogFragment);
}
ft.addToBackStack(APACHE_FRAGMENT);
m_dialogFragment = ApacheLicenseDialog.newInstance(counter);
m_dialogFragment.show(fm, APACHE_FRAGMENT);
}
最后是我的case语句,它调用此方法:
// Case 3 = Show the Apache Open Source License information
case 3:
// Launch the DialogFragment
launchApacheDialogFragment(fm, ft);
// Break out of the Statement
break;
任何帮助将不胜感激,尽管这只是阅读开放源代码许可证,但这是一种令人讨厌的冻结体验的延迟。
再次,请使用Thread / Handler / Looper意识形态帮助我。 我试图理解这个概念,而不是仅仅使用AsyncTask。
更新资料
我发现这可以使用Debug透视图进行工作。 我的线程启动,我的处理程序处理所有消息,并且在对话框片段的生命周期结束时,后台线程成功加入。 我是否忘记了需要进一步清理的东西?
谢谢
我找到了一种使用BroadcastReceiver做到这一点的更好方法,请参见此处的文章,以编程方式注册子类BroadcastReceiver onReceive(context,intent)不会在DialogFragment中被调用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.