Android:如何拥有一个(主)Activity实例或检索我需要的Activity实例?

时间:2011-09-27 15:43:00

标签: android multithreading android-activity instance

我正在开发一个执行线程的Android应用程序,并通过GUI Activity上的GUI处理程序更新GUI。 当用户将应用程序放在后台时,我需要线程运行。这样就完成了!

我的问题是,当用户通过应用历史记录或应用启动器返回时,我想返回之前运行的Activity。 相反,许多人经常会启动一个新的Activity实例。

我尝试过使用应用程序属性“launchMode”(“SingleTop”,“SingleInstance”,“SingleTask”),但我无法实现目标。

另一种方法可能是我从每个运行线程的Activity打开一个通知,但是如何打开与该通知“链接”的Activity?

我希望在你的帮助下

谢谢

修改:示例代码 为简单起见,我已将所有代码放在一个类中。

如果你尝试这个应用程序,按下底部的按钮,线程开始。现在,如果你回家打开其他应用程序,你可以看到线程再次运行,你看到吐司(这是我想要的),然后如果你返回我的应用程序,或点击通知或启动器或应用程序历史记录,可以创建一个新实例,我丢失了以前的运行。 我怎么解决这个问题?如何始终返回正在运行的活动?

TestThreadActivity.java

package tld.test;

import java.util.ArrayList;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.ToggleButton;

public class TestThreadActivity extends Activity {

    private static final int NOTIFY_THREAD_IS_RUNNING = 1;
    private MyRunnable myRunnable;
    private Thread myThread;
    // List of all message
    private ArrayList<String> responseList = new ArrayList<String>(10);
    // ListView adapter
    private ArrayAdapter<String> responseListAdapter;

    /**
     * Called when the activity is first created.
     **/
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        responseListAdapter = new ArrayAdapter<String>(this,
            R.layout.list_item, responseList);
        ListView listViewResponse = (ListView) findViewById(R.id.listViewResponse);
        listViewResponse.setAdapter(responseListAdapter);
        ToggleButton toggleButton = (ToggleButton) findViewById(R.id.startStopBtn);
        toggleButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {

             @Override
             public void onCheckedChanged(CompoundButton buttonView,
                boolean isChecked) {
                if (isChecked)
                    startThread();
                else
                    stopThread();
             }
        });
    }

    /**
     * Create and start the thread
     **/
    private void startThread() {
        // Clear listview
        responseList.clear();
        responseListAdapter.notifyDataSetChanged();
        if (myRunnable == null)
        myRunnable = new MyRunnable(guiHandler);
        myThread = new Thread(myRunnable, "myThread-" + System.currentTimeMillis());
        myThread.start();
        notifyThread();
        Toast.makeText(this, "Thread Started", Toast.LENGTH_SHORT).show();
    }

    /**
     * Stop the thread
     **/
    private void stopThread() {
        myRunnable.stop();
        cancelNotifyThread();
        Toast.makeText(this, "Thread Stopped", Toast.LENGTH_SHORT).show();
    }

    /**
     * Crea una notifica sulla barra di stato
     */
    private void notifyThread() {
        int icon = R.drawable.icon; // default icon from resources
        CharSequence tickerText = "Thread is running"; // ticker-text       
        long when = System.currentTimeMillis(); // notification time
        Context context = getApplicationContext(); // application Context
        CharSequence contentTitle = getString(R.string.app_name); // expanded
                                                                // message
                                                                // title
        CharSequence contentText = "Thread is running..."; // expanded message
                                                            // text
        Intent notificationIntent = new Intent(this, this.getClass());
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
            notificationIntent, 0);
        // the next two lines initialize the Notification, using the
        // configurations above
        Notification notification = new Notification(icon, tickerText, when);
        notification.flags |= Notification.FLAG_ONGOING_EVENT;
        notification.setLatestEventInfo(context, contentTitle, contentText,
            contentIntent);
        NotificationManager notificationManager = ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE));
        notificationManager.notify(NOTIFY_THREAD_IS_RUNNING, notification);
    }

    /**
     * Clear previous notification
     */
    private void cancelNotifyThread() {
        NotificationManager notificationManager = ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE));
        notificationManager.cancel(NOTIFY_THREAD_IS_RUNNING);
    }

    // My GUI Handler. Receive message from thread to put on Activity's listView
    final private Handler guiHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
                String newMsg = (String) msg.obj;
                // Add message to listView
            responseList.add(newMsg);
            responseListAdapter.notifyDataSetChanged();
                // and show a toast to view that is running also when it is not in
            // foreground.
            Toast.makeText(TestThreadActivity.this, newMsg, Toast.LENGTH_SHORT)
                .show();
            super.handleMessage(msg);
        }
    };

    /**
     * Simple runnable. Only wait WAIT_INTERVAL milliseconds and send a message
     * to the GUI
     **/
    public class MyRunnable implements Runnable {
        public static final int WHAT_ID = 1;
        private static final int WAIT_INTERVAL = 5000;
        private boolean isRunning;
        private int counter;
        private Handler guiHandler;

        public MyRunnable(Handler guiHandler) {
            super();
            this.guiHandler = guiHandler;
        }

        public void stop() {
            isRunning = false;
        }

        @Override
        public void run() {
            counter = 0;
            isRunning = true;
            while (isRunning) {
                // Pause
                try {
                    Thread.sleep(WAIT_INTERVAL);
                } catch (InterruptedException e) {
                }
                // Notify GUI
                Message msg = guiHandler.obtainMessage(WHAT_ID,
                    "Thread is running: " + (++counter) + " loop");
                guiHandler.sendMessage(msg);
            }
        }
    }
}

布局\ main.xml中:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ListView android:layout_width="match_parent" android:id="@+id/listViewResponse"
        android:layout_height="0dip" android:layout_weight="1.0" android:transcriptMode="normal"></ListView>
    <ToggleButton android:id="@+id/startStopBtn"
        android:layout_height="wrap_content" android:layout_width="match_parent" android:textOn="@string/toggleBtnStop" android:textOff="@string/toggleBtnStart"></ToggleButton>
</LinearLayout>

布局\ list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp"
    android:textSize="16sp" >
</TextView>

值\ strings.xml中:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">TestThread</string>
    <string name="toggleBtnStart">Start Thread</string>
    <string name="toggleBtnStop">Stop Thread</string>
</resources>

1 个答案:

答案 0 :(得分:0)

我已经解决了!

问题是Back按钮破坏了活动。 然后我覆盖onBackPressed方法并询问用户是退出还是让活动继续运行。此外,我已经设置了 launchMode =“singleTop”

比我想象的容易;)

但是我有一个疑问:应用程序如何在销毁之后运行?在按下后退按钮后也可以看到吐司。什么被摧毁呢?