Android 多线程应用程序崩溃
我的程序结构如下。我有以下主要活动。此活动将创建一个“确定位置”对象。该确定位置对象将接受一些参数。其中有一个将结果传递给的处理程序。下面我传入了 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您似乎只是实例化了一条
Message
,将其连续写入后台线程,然后从 UI 线程连续读取它,而无需同步。事情的繁荣并不奇怪。您可以通过对跨线程边界发送的每条消息使用
Message.obtain()
来解决此问题,也可以通过使用AsyncTask
。使用
AsyncTask
,您不需要任何Handlers
或Runnables
...它使线程化变得尽可能简单。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 anAsyncTask
.With an
AsyncTask
you don't need anyHandlers
orRunnables
... it makes threading as simple as it ought to be.