繁体   English   中英

使用Thread / Handler / Looper for Worker Thread Android

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM