android中Thread对于Adapter出现的报错情况的处理以及如何正确使用Spinner与SimpleCurosorAdapter
2015-07-16 15:55
666 查看
在开始之前,先说说这个博文的意思,因为之前有个小项目用到的是spinner与本地数据库 的数据 的连接,然后spinner会在Actiivity出现后马上调用数据库的数据,也就是在onCreate中实现这个功能。然后对于这块也确实出现了一些意想不到的错误,导致引导错了方向,所以Logcat出现的问题也是比较难以理解的。现在开始讲解代码。
先展示先前写的代码和报错的原因:
package com.example.hello;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Contacts.People;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Spinner;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
public Spinner listView;
SimpleCursorAdapter listAdapter = null;
Cursor cursor = null;
Handler handler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
if(msg.what == 0x123)
{
if(listAdapter !=null)
{
listView.setAdapter(listAdapter);
}
else
{
Toast.makeText(MainActivity.this, "listAdapter为空", Toast.LENGTH_LONG).show();
}
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (Spinner)findViewById(R.id.list);
new Thread()
{
public void run()
{
cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
startManagingCursor(cursor);
listAdapter= new SimpleCursorAdapter(MainActivity.this, android.R.layout.simple_expandable_list_item_1, cursor, new String[]{People.NAME}, new int[]{android.R.id.text1});
handler.sendEmptyMessage(0x123);
};
}.start();
}
}
后面需要在注册表里添加权限:<uses-permission
android:name="android.permission.READ_CONTACTS"
/>
这是一个Activity,然后Spinner在Layout里,我也是简单的设置一下,没有太多的花俏,在这段代码里我要实现的功能就是在新线程里调用数据库生成Cursor,然后接着在线程的run()里生成SimpleCursorAdapter,就是代码里的listAdapter。然后接下去就是给handler发送消息,通知更改界面,思路是这样子的,然后就出现错误:
07-16 07:34:13.356: E/AndroidRuntime(3954): FATAL EXCEPTION: Thread-119
07-16 07:34:13.356: E/AndroidRuntime(3954): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
07-16 07:34:13.356: E/AndroidRuntime(3954): at android.os.Handler.<init>(Handler.java:121)
07-16 07:34:13.356: E/AndroidRuntime(3954): at android.support.v4.widget.CursorAdapter$ChangeObserver.<init>(CursorAdapter.java:455)
07-16 07:34:13.356: E/AndroidRuntime(3954): at android.support.v4.widget.CursorAdapter.init(CursorAdapter.java:176)
07-16 07:34:13.356: E/AndroidRuntime(3954): at android.support.v4.widget.CursorAdapter.<init>(CursorAdapter.java:122)
07-16 07:34:13.356: E/AndroidRuntime(3954): at android.support.v4.widget.ResourceCursorAdapter.<init>(ResourceCursorAdapter.java:54)
07-16 07:34:13.356: E/AndroidRuntime(3954): at android.support.v4.widget.SimpleCursorAdapter.<init>(SimpleCursorAdapter.java:63)
07-16 07:34:13.356: E/AndroidRuntime(3954): at com.example.hello.MainActivity$2.run(MainActivity.java:43)
07-16 07:34:13.432: D/libEGL(3954): loaded /system/lib/egl/libEGL_genymotion.so
07-16 07:34:13.432: D/(3954): HostConnection::get() New Host Connection established 0xb7e4be08, tid 3954
然后经过有一次意外的思路,终于把问题给解决了:给出代码:
package com.example.hello;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Contacts.People;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Spinner;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
public Spinner listView;
SimpleCursorAdapter listAdapter = null;
Cursor cursor = null;
Handler handler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
if(msg.what == 0x123)
{
listAdapter= new SimpleCursorAdapter(MainActivity.this, android.R.layout.simple_expandable_list_item_1, cursor, new String[]{People.NAME}, new int[]{android.R.id.text1});
if(listAdapter !=null)
{
listView.setAdapter(listAdapter);
}
else
{
Toast.makeText(MainActivity.this, "listAdapter为空", Toast.LENGTH_LONG).show();
}
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (Spinner)findViewById(R.id.list);
new Thread()
{
public void run()
{
cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
startManagingCursor(cursor);
handler.sendEmptyMessage(0x123);
};
}.start();
}
}
上面的代码终于实现了想要的功能,在这里补充一下,在安卓很久以前的版本,应该是2点的安卓版本的时候,安卓是允许在主线程里实现耗时操作的,可是因为这个会影响客户的体验,所以后面就改成在新线程thread里进行耗时操作,不允许在新线程进行ui更新,然后在handler里进行ui更新。所以上面错误的问题bug就是这个方面的原因,SimpleSursorAdapter是一个界面,所以不应该在新线程里实现SimpleCursorAdapter,所以导致了上面总总看不懂原因的错误在。
最后在这里,想搞笑一下,终于把问题解决了,好开心,屌丝程序员慢慢地要走上正轨了,加油!!!!!!
先展示先前写的代码和报错的原因:
package com.example.hello;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Contacts.People;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Spinner;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
public Spinner listView;
SimpleCursorAdapter listAdapter = null;
Cursor cursor = null;
Handler handler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
if(msg.what == 0x123)
{
if(listAdapter !=null)
{
listView.setAdapter(listAdapter);
}
else
{
Toast.makeText(MainActivity.this, "listAdapter为空", Toast.LENGTH_LONG).show();
}
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (Spinner)findViewById(R.id.list);
new Thread()
{
public void run()
{
cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
startManagingCursor(cursor);
listAdapter= new SimpleCursorAdapter(MainActivity.this, android.R.layout.simple_expandable_list_item_1, cursor, new String[]{People.NAME}, new int[]{android.R.id.text1});
handler.sendEmptyMessage(0x123);
};
}.start();
}
}
后面需要在注册表里添加权限:<uses-permission
android:name="android.permission.READ_CONTACTS"
/>
这是一个Activity,然后Spinner在Layout里,我也是简单的设置一下,没有太多的花俏,在这段代码里我要实现的功能就是在新线程里调用数据库生成Cursor,然后接着在线程的run()里生成SimpleCursorAdapter,就是代码里的listAdapter。然后接下去就是给handler发送消息,通知更改界面,思路是这样子的,然后就出现错误:
07-16 07:34:13.356: E/AndroidRuntime(3954): FATAL EXCEPTION: Thread-119
07-16 07:34:13.356: E/AndroidRuntime(3954): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
07-16 07:34:13.356: E/AndroidRuntime(3954): at android.os.Handler.<init>(Handler.java:121)
07-16 07:34:13.356: E/AndroidRuntime(3954): at android.support.v4.widget.CursorAdapter$ChangeObserver.<init>(CursorAdapter.java:455)
07-16 07:34:13.356: E/AndroidRuntime(3954): at android.support.v4.widget.CursorAdapter.init(CursorAdapter.java:176)
07-16 07:34:13.356: E/AndroidRuntime(3954): at android.support.v4.widget.CursorAdapter.<init>(CursorAdapter.java:122)
07-16 07:34:13.356: E/AndroidRuntime(3954): at android.support.v4.widget.ResourceCursorAdapter.<init>(ResourceCursorAdapter.java:54)
07-16 07:34:13.356: E/AndroidRuntime(3954): at android.support.v4.widget.SimpleCursorAdapter.<init>(SimpleCursorAdapter.java:63)
07-16 07:34:13.356: E/AndroidRuntime(3954): at com.example.hello.MainActivity$2.run(MainActivity.java:43)
07-16 07:34:13.432: D/libEGL(3954): loaded /system/lib/egl/libEGL_genymotion.so
07-16 07:34:13.432: D/(3954): HostConnection::get() New Host Connection established 0xb7e4be08, tid 3954
然后经过有一次意外的思路,终于把问题给解决了:给出代码:
package com.example.hello;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Contacts.People;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Spinner;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
public Spinner listView;
SimpleCursorAdapter listAdapter = null;
Cursor cursor = null;
Handler handler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
if(msg.what == 0x123)
{
listAdapter= new SimpleCursorAdapter(MainActivity.this, android.R.layout.simple_expandable_list_item_1, cursor, new String[]{People.NAME}, new int[]{android.R.id.text1});
if(listAdapter !=null)
{
listView.setAdapter(listAdapter);
}
else
{
Toast.makeText(MainActivity.this, "listAdapter为空", Toast.LENGTH_LONG).show();
}
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (Spinner)findViewById(R.id.list);
new Thread()
{
public void run()
{
cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
startManagingCursor(cursor);
handler.sendEmptyMessage(0x123);
};
}.start();
}
}
上面的代码终于实现了想要的功能,在这里补充一下,在安卓很久以前的版本,应该是2点的安卓版本的时候,安卓是允许在主线程里实现耗时操作的,可是因为这个会影响客户的体验,所以后面就改成在新线程thread里进行耗时操作,不允许在新线程进行ui更新,然后在handler里进行ui更新。所以上面错误的问题bug就是这个方面的原因,SimpleSursorAdapter是一个界面,所以不应该在新线程里实现SimpleCursorAdapter,所以导致了上面总总看不懂原因的错误在。
最后在这里,想搞笑一下,终于把问题解决了,好开心,屌丝程序员慢慢地要走上正轨了,加油!!!!!!
相关文章推荐
- 智能储物柜/快递柜系统解析<一>
- Android中ListView(一)分页加载数据
- java&nbsp;判断&nbsp;android、iph…
- 最流行的android组件大全
- android webview响应web页面js
- Android使用命令创建项目并打包安装
- Android--sharepreference总结
- Android InputMethodManager输入法简介
- android帮助文档打开慢
- android依赖注入框架Butter Knife的使用。
- Android学习之SQLite学习
- android-LV数据源初始化异常
- Android圆形向外扩散颜色渐浅动画
- Android Studio 基本设置图解教程
- android listview 不能点击 descendantFocusability
- Android APK 签名 (转发)
- android之apk自动更新采用Notification通知提示并显示下载进度
- 通过浏览器直接打开Android应用程序
- Android开源项目分类汇总
- 一个经过改良过的android下拉刷新控件