[英]Using Thread/Handler/Looper for Worker Thread Android
Having some responsiveness issues when implementing the Thread/Handler/Looper ideology to process information in the background by passing messages. 实施Thread / Handler / Looper意识形态以通过传递消息在后台处理信息时,存在一些响应性问题。 I really don't want to use the AsyncTask class, since i already know how to use that to accomplish what I am trying to do.
我真的不想使用AsyncTask类,因为我已经知道如何使用它来完成我想做的事情。
Can someone help me with the following code that downloads the Apache License using the GooglePlayServicesUtil class and displays it in a TextView inside a DialogFragment ? 有人可以帮我使用以下代码,这些代码使用GooglePlayServicesUtil类下载Apache许可证,并在DialogFragment内的TextView中显示它吗?
My biggest issue is that when i launch it, sometimes it is fast but others it is very slow to show the DialogFragment. 我最大的问题是,当我启动它时,有时显示DialogFragment的速度很快,但另一些则非常慢。 Maybe I am not following the best practice for loading the DialogFragment, i don't really know.
我真的不知道,也许我没有遵循最佳实践来加载DialogFragment。
Update Added code that is now working, but for some reason I still get a UI Freeze once in a while. 更新添加的代码现在可以正常工作,但是由于某种原因,我仍然会偶尔获得UI Freeze。 Does anyone know if this is device specific?
有人知道这是否特定于设备吗? I am currently on a Samsung GS3.
我目前正在使用三星GS3。 .
。 .
。
My DialogFragment: 我的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;
}
}
}
And i show this by using a switch statement as such: 我通过使用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);
}
And finally my case statement which calls this method: 最后是我的case语句,它调用此方法:
// Case 3 = Show the Apache Open Source License information
case 3:
// Launch the DialogFragment
launchApacheDialogFragment(fm, ft);
// Break out of the Statement
break;
Any help would be appreciated, this is kind of an annoying freeze delaying the experience, although its just to read the open source license. 任何帮助将不胜感激,尽管这只是阅读开放源代码许可证,但这是一种令人讨厌的冻结体验的延迟。
Again, please help me using the Thread/Handler/Looper ideology. 再次,请使用Thread / Handler / Looper意识形态帮助我。 I am trying to understand this concept as opposed to just using AsyncTask.
我试图理解这个概念,而不是仅仅使用AsyncTask。
Update 更新资料
I have found this to be working using Debug perspective. 我发现这可以使用Debug透视图进行工作。 My thread starts up and my handler processes all the messages and at the end of the lifecycle of my dialog fragment the background thread successfully joins.
我的线程启动,我的处理程序处理所有消息,并且在对话框片段的生命周期结束时,后台线程成功加入。 Am i forgetting something that needs to be cleaned up more?
我是否忘记了需要进一步清理的东西?
Thanks 谢谢
我找到了一种使用BroadcastReceiver做到这一点的更好方法,请参见此处的文章,以编程方式注册子类BroadcastReceiver onReceive(context,intent)不会在DialogFragment中被调用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.