Loader和Fragment都是Android 3.0的新特性,有关Fragment相关的内容Android开发网已经用了多个篇幅介绍,而Loader相关的大家可以通过 LoaderManager - Android 3.0新特性 一文了解Loader的作用和结构,下面就以一个简单的工程示例代码了解下Loader。
public class FragmentListCursorLoader extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fm = getFragmentManager(); //获取FragmentManager这个服务实例
if (fm.findFragmentById(android.R.id.content) == null) { //这个资源是android内部的布局,注意是android.R
CursorLoaderListFragment list = new CursorLoaderListFragment();
fm.beginTransaction().add(android.R.id.content, list).commit();
}
}
public static class CursorLoaderListFragment extends ListFragment
implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {
SimpleCursorAdapter mAdapter; //这里使用简单cursor适配器绑定数据库
String mCurFilter;
@Override public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setEmptyText("No phone numbers");
setHasOptionsMenu(true); //显示actionbar,如果不明白看android123以前的文章
mAdapter = new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_2, null,
new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
new int[] { android.R.id.text1, android.R.id.text2 }, 0);
setListAdapter(mAdapter);
getLoaderManager().initLoader(0, null, this);
}
@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
MenuItem item = menu.add("Search");
item.setIcon(android.R.drawable.ic_menu_search);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
SearchView sv = new SearchView(getActivity());
sv.setOnQueryTextListener(this);
item.setActionView(sv);
}
public boolean onQueryTextChange(String newText) {
mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
getLoaderManager().restartLoader(0, null, this);
return true;
}
@Override public boolean onQueryTextSubmit(String query) {
return true;
}
@Override public void onListItemClick(ListView l, View v, int position, long id) {
Log.i("FragmentComplexList", "Item clicked: " + id);
}
static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
Contacts._ID,
Contacts.DISPLAY_NAME,
Contacts.CONTACT_STATUS,
Contacts.CONTACT_PRESENCE,
Contacts.PHOTO_ID,
Contacts.LOOKUP_KEY,
};
public Loader<Cursor> onCreateLoader(int id, Bundle args) { //这里的处理是异步的
Uri baseUri;
if (mCurFilter != null) {
baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
Uri.encode(mCurFilter));
} else {
baseUri = Contacts.CONTENT_URI;
}
String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
+ Contacts.DISPLAY_NAME + " != '' ))";
return new CursorLoader(getActivity(), baseUri,
CONTACTS_SUMMARY_PROJECTION, select, null,
Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data); //处理完成
}
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
}
}
JAVA以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。 JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。
- 运行环境
CPU : AMD Moblie Athlon 64 3200+
Mem : 1024 MBOS : Windows xp sp2
JDK : java version "1.5.0_06"
IDE : Eclipse 3.1.2 、 Microsoft Visual Studio 2005
- 编写JAVA 代码
//JNITest.java
/**
* @author chunyv
*
*/
public class JNITest {/**
* @param args
*/
static
{
try
{
System.loadLibrary("JNITest");
}
catch(Exception e)
{
System.out.println("load library failure!");
}
}
public native static void version();
public native static void setint(int i);
public native static int getint();
public native static void setstr(String str);
public native static String getstr();
public native static void setgbk(byte[] gbkstr);
public native static byte[] getgbk();
public static void main(String[] args) {
// TODO Auto-generated method stub
String test = "Hello World!";
String test2 = "你好!\n\t\t--chunyv";
System.out.println("Proc Start");
byte[] end = {0};try
{
byte[] mybytedb = test2.getBytes("gbk");
byte[] mybyte = new byte[mybytedb.length + end.length];
System.arraycopy(mybytedb , 0 , mybyte , 0 ,mybytedb.length);
System.arraycopy(end , 0 , mybyte , mybytedb.length , end.length);
JNITest jnitest = new JNITest();
jnitest.setint(6);
System.out.println("setint ok");
System.out.println("get int form library :"+jnitest.getint());
System.out.println("getint ok");
jnitest.setstr(test);
System.out.println("setstr ok");
System.out.println(jnitest.getstr());
System.out.println("getstr ok");
jnitest.setgbk(mybyte);
System.out.println("setgbk ok");
System.out.println(jnitest.getgbk());
System.out.println("getgbk ok");
jnitest.version();
}
catch(Exception e)
{
e.printStackTrace();
}
}}
- 生成 .h 文件
javac JNITest.java
javah JNITest
- 实现 JNITest.h 中的方法
/*
* author chunyv
* JNITest dll
*/#include "JNITest.h"
#include <windows.h>
JNIEXPORT void JNICALL Java_JNITest_version
(JNIEnv *, jclass)
{
printf("JNI Test\n\t\t--chunyv");
}
JNIEXPORT void JNICALL Java_JNITest_setint
(JNIEnv *, jclass, jint ii)
{
i = ii;
}
JNIEXPORT jint JNICALL Java_JNITest_getint
(JNIEnv *, jclass)
{
return i;
}
JNIEXPORT void JNICALL Java_JNITest_setstr
(JNIEnv * env, jclass, jstring jstr)
{
jboolean test = true;memset(str , 0 , sizeof(str));
sprintf_s(str ,env->GetStringUTFChars(jstr,&test));
env->ReleaseStringUTFChars(jstr , NULL);
}JNIEXPORT jstring JNICALL Java_JNITest_getstr
(JNIEnv * env, jclass)
{
return WindowsTojstring(env , str);
}JNIEXPORT void JNICALL Java_JNITest_setgbk
(JNIEnv * env, jclass, jbyteArray myjbyte)
{
memset(strgbk , 0 , sizeof(strgbk));sprintf_s(strgbk ,(char *)env->GetByteArrayElements(myjbyte,0));
}JNIEXPORT jstring JNICALL Java_JNITest_getgbk
(JNIEnv * env, jclass)
{
return WindowsTojstring(env , strgbk);
}jstring WindowsTojstring( JNIEnv* env, char* str_tmp )
{
jstring rtn = 0;
int slen = (int)strlen(str_tmp);
unsigned short * buffer = 0;
if( slen == 0 )
{
rtn = env->NewStringUTF(str_tmp );
}
else
{
int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str_tmp, slen, NULL, 0 );buffer = (unsigned short *)malloc( length*2 + 1 );
if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str_tmp, slen, (LPWSTR)buffer, length ) >0 )
{
rtn = env->NewString( (jchar*)buffer, length );
}
}if( buffer )
{
free( buffer );
}return rtn;
}
- 将生成的JNITest.dll 放到 .class 所在的目录 测试
java JNITestProc Start
setint ok
get int form library :6
getint ok
setstr ok
Hello World!
getstr ok
setgbk ok
你好!
--chunyv
getgbk ok
JNI Test
--chunyv
JNI 在 FreeBSD 上的应用
- 运行环境
CPU : Intel(R) Pentium(R) 4 CPU 2.40GHz (2393.94-MHz 686-class CPU)
Mem : 512 MB
OS : FreeBSD 6.2-PRERELEASE
JDK : java version "1.5.0"
IDE : vim + gcc 3.4.4
- java代码同上
- 生成 .h 文件同上
- 实现 JNITest.h 中的方法
/*
* author chunyv
* JNITest so
* add "int FreeBSD2Jstring(char * src ,
* char * dst,
* int * len);" into JNITest.h
*/#include <stdio.h>
#include <iconv.h>
#include <stdlib.h>
#include <string.h>
#include "JNITest.h"int i = 0;
char str[1024];
char strgbk[1024];JNIEXPORT void JNICALL Java_JNITest_version
(JNIEnv *env, jclass jc)
{
printf("JNI Test\n\t\t--chunyv\n");
}
JNIEXPORT void JNICALL Java_JNITest_setint
(JNIEnv * env, jclass jc, jint ii)
{
i = ii;
}
JNIEXPORT jint JNICALL Java_JNITest_getint
(JNIEnv * env, jclass jc)
{
return i;
}
JNIEXPORT void JNICALL Java_JNITest_setstr
(JNIEnv * env, jclass jc, jstring jstr)
{
jboolean test = 1;memset(str , 0 , sizeof(str));
sprintf(str ,(*env)->GetStringUTFChars(env ,jstr,&test));
(*env)->ReleaseStringUTFChars(env ,jstr , NULL);
}JNIEXPORT jstring JNICALL Java_JNITest_getstr
(JNIEnv * env, jclass jc)
{
return (*env)->NewStringUTF(env ,str);
}JNIEXPORT void JNICALL Java_JNITest_setgbk
(JNIEnv * env, jclass jc, jbyteArray myjbyte)
{
memset(strgbk , 0 , sizeof(strgbk));sprintf(strgbk ,(char *)(*env)->GetByteArrayElements(env ,myjbyte,0));
}JNIEXPORT jstring JNICALL Java_JNITest_getgbk
(JNIEnv * env, jclass jc)
{
char test[1024] ;
sprintf(test ,strgbk);
int len = (int ) strlen(strgbk);
if( FreeBSD2Jstring(test , strgbk ,&len ))
{
printf("convert error\n");
return NULL;
}
return (*env)->NewStringUTF(env ,strgbk);
}int FreeBSD2Jstring(char * src ,
char * dst,
int * len)
{
size_t n_in = strlen(src);
size_t n_out = *len+2;
memset(dst , 0 , n_out);
iconv_t test = iconv_open("UTF-8","GBK");
if(test == (iconv_t)-1)
{
printf("iconv open error\n");
return -1;
}
if((size_t)-1 == iconv(test ,(const char **) & src ,&n_in , & dst , &n_out))
{
printf("iconv convert error\n");
return -1;
}
if(test)
{
iconv_close(test);
}*len = n_out;
return 0;
}
- 编译 .c 文件,将生成的库文件放到.class 所在目录并测试 .class
编译库文件
gcc -Wall -fPIC -shared -o libJNITest.so -I /usr/local/diablo-jdk1.5.0/include/ -I /usr/local/diablo-jdk1.5.0/include/freebsd/ -I /usr/local/include/ -liconv -L /usr/local/lib/ JNITest.c
测试 .class
java -Djava.library.path=./ JNITest
- 测试结果
Proc Start
setint ok
get int form library :6
getint ok
setstr ok
Hello World!
getstr ok
setgbk ok
你好!
--chunyv
getgbk ok
JNI Test
--chunyv
JNI在Linux上的使用请参阅 《JNI在FreeBSD上的使用》部分
注:实例仅供参考,转载请注明出处,欢迎交流学习,谢谢!!
为了保证我们的应用程序保持响应,一个好的实践就是将执行缓慢的、计算耗时的操作从应用程序的主线程移进一个子线程中。
注意 :所有的Android应用程序——包括Activity、Service和Broadcast Receivers——在应用程序主线程中启动。因此,任何组件中耗时的操作将会阻塞包括Service和不可见的Activity等其他组件。
对于后台进程,Android提供了两种选择方案。先说下AsyncTask类,通过AsyncTask可以定义一个在后台执行的操作,然后提供一个事件处理程序,这样就可以用这个程序监控进程并且传递结果到GUI线程中。
或者,你也可以实现自己的线程,使用处理程序类在更新界面UI前和GUI线程做同步。这两种技术我们都会在下文提到。
使用后台线程对于避免对话框的“强制关闭”非常重要。Android中,Activity在5秒中内对于输入事件(如键盘按下)没有响应,Broadcast Receivers在10秒钟没有完成onReceive的处理,都被认为是没有回复的。
你不仅仅只想避免这种情况的发生,更不想对话框关闭。那就是用后台线程处理这些耗时操作吧,包括文件操作、网络查找、数据库事务和复杂计算。
使用AsyncTask运行异步任务
AsyncTask类提供了一种既简单又方便的途径就可以将你的耗时操作移到后台线程进行。与GUI线程异步同步的处理程序可以让你方便的在任务完成后更新Views控件和其他的UI元素的结果。
AsyncTask处理着所有线程的创建、管理和异步刷新,使你能够创建一个异步同步任务在操作完成后维护后台操作和UI更新的处理的一致性。
异步同步任务的创建
你需要从AsyncTask继承来创建你的异步同步任务,如代码清单1所示。你的实现应该指明方法execute的入参类型,后台计算执行过程的进度类型, 后台线程执行返回结果类型,具体参数格式如下:
AsyncTask<[Input Parameter Type], [Progress Report Type], [Result Type]>
如果你不需要输入参数、更新进度或者返回值,只需简单的指定相应的类型为Void。
代码清单1:
private class MyAsyncTask extends AsyncTask<String, Integer, Integer> {
@Override
protected void onProgressUpdate(Integer... progress) {
// [... Update progress bar, Notification, or other UI element ...]
}
@Override
protected void onPostExecute(Integer... result) {
// [... Report results via UI update, Dialog, or notification ...]
}
@Override
protected Integer doInBackground(String... parameter) {
int myProgress = 0;
// [... Perform background processing task, update myProgress ...]
PublishProgress(myProgress)
// [... Continue performing background processing task ...]
// Return the value to be passed to onPostExecute
return result;
}
}
代码清单1说明你的子类应该实现以下几个事件处理函数:
1.doInBackground
需要在你的实现类里定义了类型的一组参数,这个方法会在后台线程中执行,所以不能在UI里面调用。
耗时代码通常写在这儿,使用publishProgress方法通过onProgressUpdate将进度更新到UI中。当你的后台任务完成后,返回值将被传递到onPostExecute处理程序中反馈给UI。
2.onProgressUpdate
重写此方法传递过程中的更新到UI线程中。该方法接收一组由doInBackground传递来的参数将其传入publishProgress。此方法被执行的时候和GUI线程做同步,所以你可以安全的修改你的UI元素。
3.onPostExecute
当doInBackground执行完以后,返回值将被传入这个事件处理函数中。
一旦你的异步刷新任务完成,就可使用此方法去更新UI。此方法是同步刷版伴随着GUI线程的执行,因此你可以安全的修改UI元素。
执行异步同步任务
一旦你实现了你的异步同步任务,通过创建一个实例和调用execute就可以执行你的任务,如代码清单2所示。你可以传入一些参数,这些参数的类型在你的实现里面已经定义过了。
代码清单2:
new MyAsyncTask().execute("inputString1", "inputString2");
注意:每个AsyncTask仅可以被执行一次,如果你尝试再一次调用execute将会抛出一个异常。