Android 多线程应用程序崩溃

发布于 2024-10-17 01:49:20 字数 2747 浏览 2 评论 0原文

我的程序结构如下。我有以下主要活动。此活动将创建一个“确定位置”对象。该确定位置对象将接受一些参数。其中有一个将结果传递给的处理程序。下面我传入了 MyThreadHandler 类型的 threadHandler (处理程序的扩展)。该DetermineLocation 对象实现了runnable,并在run 方法中查询GPS 并将结果在消息中传递给threadHandler(传递到DetLoc 对象中)。 threadHandler 实例在创建时接收一个 textview 对象(这是要更新的文本视图)。

出于调试目的,我禁用了 GPS 更新功能,并且仅让 DetLoc 的 run 方法传递一个随机数。然而,这仍然使我的程序崩溃。

崩溃主要发生在向设备推送大量输入时(例如非常快地在多个位置按下屏幕)。这肯定是一个线程问题,但我不明白为什么。

主要:

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    threadModifiedText = (TextView) findViewById(R.id.thread_modified_text);

    threadHandler = new MyHandler(threadModifiedText);

    //Start up the DetermineLocation thread.  This thread will query the GPS every N milliseconds.
    // then push the results over hte network if at all possible
    DetermineLocation detLoc = new DetermineLocation(this, threadHandler, 3000);
    Thread detLocThread = new Thread(detLoc);
    detLocThread.start();
}

也是主要:

class MyHandler extends Handler{

private TextView threadModifiedText;
public MyHandler(TextView tv) {
    threadModifiedText = tv;
}

 public void handleMessage(Message msg) {
        // whenever the Thread notifies this handler we have
        // only this behavior
        threadModifiedText.setText((CharSequence)msg.obj);
 }
}

DetermineLocation 类(如您所见,GPS 内容已被注释掉,并且仍然崩溃):

public class DetermineLocation implements Runnable {
private int updateInterval;
private int provider=3;
private Handler threadHandler;
private Context c;

public final int GPS_ONLY=1;
public final int NETWORK_ONLY=2;
public final int ANY_AVAILABLE=3;

public DetermineLocation(Context c, Handler h, int ui) {
    this.c = c;
    this.updateInterval = ui;
    this.threadHandler = h;

}

public void changeProvider(int providerConst) { 
    if(providerConst <=3 && providerConst >= 1)
        provider = providerConst;
}

public void changeUpdateInterval(int updateIntervalMS) {
    if(updateIntervalMS >= 0)
        this.updateInterval = updateIntervalMS;
}

@Override
public void run() {
    Message m = new Message();
    //LocationManager locationManager = (LocationManager)c.getSystemService(Context.LOCATION_SERVICE); 
    //Location loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

    while(true) {

    CharSequence cs = Math.random() + "\r\n"; //+ loc.getLatitude() + " " + loc.getLongitude();
    m.obj = cs;
    threadHandler.sendMessage(m);

    try {
        Thread.sleep(updateInterval);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    }

}

My program is structured as followed. I have the following main activity. This activity will create a "Determine Location" object. This Determine location object will take in a few parameters. Amongst them is a handler to pass the results along to. In the following I pass in threadHandler which is of type MyThreadHandler (an extension of handler). This DetermineLocation object implements runnable and in the run method it queries the GPS and passes the results along in a message to threadHandler (passed into the DetLoc object). The threadHandler instance takes in a textview object upon creation (this is the text view to update)

For debugging purposes I have disabled the GPS update feature and only had DetLoc's run method pass a random number. This however is still crashing my program.

The crash mainly happens while pushing a lot of input to the device (such as pressing the screen in multiple places really fast). This is a thread issue for sure but I do not see why.

MAIN:

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    threadModifiedText = (TextView) findViewById(R.id.thread_modified_text);

    threadHandler = new MyHandler(threadModifiedText);

    //Start up the DetermineLocation thread.  This thread will query the GPS every N milliseconds.
    // then push the results over hte network if at all possible
    DetermineLocation detLoc = new DetermineLocation(this, threadHandler, 3000);
    Thread detLocThread = new Thread(detLoc);
    detLocThread.start();
}

ALSO MAIN:

class MyHandler extends Handler{

private TextView threadModifiedText;
public MyHandler(TextView tv) {
    threadModifiedText = tv;
}

 public void handleMessage(Message msg) {
        // whenever the Thread notifies this handler we have
        // only this behavior
        threadModifiedText.setText((CharSequence)msg.obj);
 }
}

DetermineLocation class (as you can see the GPS stuff has been commented out and its still crashing):

public class DetermineLocation implements Runnable {
private int updateInterval;
private int provider=3;
private Handler threadHandler;
private Context c;

public final int GPS_ONLY=1;
public final int NETWORK_ONLY=2;
public final int ANY_AVAILABLE=3;

public DetermineLocation(Context c, Handler h, int ui) {
    this.c = c;
    this.updateInterval = ui;
    this.threadHandler = h;

}

public void changeProvider(int providerConst) { 
    if(providerConst <=3 && providerConst >= 1)
        provider = providerConst;
}

public void changeUpdateInterval(int updateIntervalMS) {
    if(updateIntervalMS >= 0)
        this.updateInterval = updateIntervalMS;
}

@Override
public void run() {
    Message m = new Message();
    //LocationManager locationManager = (LocationManager)c.getSystemService(Context.LOCATION_SERVICE); 
    //Location loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

    while(true) {

    CharSequence cs = Math.random() + "\r\n"; //+ loc.getLatitude() + " " + loc.getLongitude();
    m.obj = cs;
    threadHandler.sendMessage(m);

    try {
        Thread.sleep(updateInterval);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

胡大本事 2024-10-24 01:49:20

您似乎只是实例化了一条 Message,将其连续写入后台线程,然后从 UI 线程连续读取它,而无需同步。事情的繁荣并不奇怪。

您可以通过对跨线程边界发送的每条消息使用 Message.obtain() 来解决此问题,也可以通过使用 AsyncTask

使用AsyncTask,您不需要任何HandlersRunnables...它使线程化变得尽可能简单。

You appear to be instantiating just the one Message, writing it continuously on your background thread, and then reading it continuously from your UI thread, with no synchronization. It's not surprising things go boom.

You can fix this either by using Message.obtain() for each message you send across the thread boundary, or you can make your life a whole lot simpler by using an AsyncTask.

With an AsyncTask you don't need any Handlers or Runnables... it makes threading as simple as it ought to be.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文