使用Thread / Handler / Looper for Worker Thread Android

时间:2014-03-26 20:06:15

标签: java android multithreading

在实现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透视图。我的线程启动,我的处理程序处理所有消息,并在我的对话框片段的生命周期结束时后台线程成功加入。我忘记了需要清理的东西吗?

由于

1 个答案:

答案 0 :(得分:0)