在实现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透视图。我的线程启动,我的处理程序处理所有消息,并在我的对话框片段的生命周期结束时后台线程成功加入。我忘记了需要清理的东西吗?
由于
答案 0 :(得分:0)
我发现使用BroadcastReceiver更好的方法,请参阅此处的帖子Programmatically Registering Child Class BroadcastReceiver onReceive(context, intent) not getting called in DialogFragment