常用简单的ContentProvider的实现差不多,整理了个通用的(基于com.example.android.supportv4.app.LoaderThrottleSupport.SimpleProvider修改), 从这个类继承,再重写几个方法就可以了,测试代码见附件。
import java.util.HashMap; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.provider.BaseColumns; import android.support.v4.database.DatabaseUtilsCompat; import android.text.TextUtils; /** * * @author J * */ public abstract class SimpleContentProvider extends ContentProvider{ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.%s.%s"; public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.%s.%s"; private final UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); // private HashMap<Integer, String> hash_id_tableName = new HashMap<Integer, String>(); private SQLiteOpenHelper mOpenHelper; protected abstract String getAuthority(); protected abstract SQLiteOpenHelper createDatabaseHelper(Context context); protected abstract String[] getTableNames(); protected String getIdName(String tableName){ return BaseColumns._ID; } protected String getDefaultSort(String tableName){ return null; } /** * If URI is main table */ private boolean isMain(int id){ return id % 2 == 1; } /** * Global provider initialization. */ public SimpleContentProvider() { int id_main = 1, id_row = 2; String[] tableNames = getTableNames(); for (String tableName : tableNames){ //奇数 for main table, 偶数 for row mUriMatcher.addURI(getAuthority(), tableName, id_main); mUriMatcher.addURI(getAuthority(), tableName + "/#", id_row); hash_id_tableName.put(id_main, tableName); hash_id_tableName.put(id_row, tableName); id_main += 2; id_row += 2; } } @Override public boolean onCreate() { mOpenHelper = createDatabaseHelper(getContext()); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Constructs a new query builder and sets its table name SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); int id = mUriMatcher.match(uri); String tableName = hash_id_tableName.get(id); if (tableName != null){ qb.setTables(tableName); if (isMain(id)){ //qb.setProjectionMap(mNotesProjectionMap); } else{ //qb.setProjectionMap(mNotesProjectionMap); qb.appendWhere(getIdName(tableName) + "=?"); selectionArgs = DatabaseUtilsCompat.appendSelectionArgs(selectionArgs, new String[] { uri.getLastPathSegment() }); } } else{ throw new IllegalArgumentException("Unknown URI " + uri); } if (TextUtils.isEmpty(sortOrder)) { sortOrder = getDefaultSort(tableName); } SQLiteDatabase db = mOpenHelper.getReadableDatabase(); Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } /** * Return the MIME type for an known URI in the provider. */ @Override public String getType(Uri uri) { int id = mUriMatcher.match(uri); String tableName = hash_id_tableName.get(id); if (tableName != null){ if (isMain(id)){ return String.format(CONTENT_TYPE, getAuthority(), tableName); } else{ return String.format(CONTENT_ITEM_TYPE, getAuthority(), tableName); } } else{ throw new IllegalArgumentException("Unknown URI " + uri); } } /** * Handler inserting new data. */ @Override public Uri insert(Uri uri, ContentValues initialValues) { int id = mUriMatcher.match(uri); String tableName = hash_id_tableName.get(id); if (tableName == null || !isMain(id)){ // Can only insert into to main URI. throw new IllegalArgumentException("Unknown URI " + uri); } ContentValues values; if (initialValues != null) { values = new ContentValues(initialValues); } else { values = new ContentValues(); } SQLiteDatabase db = mOpenHelper.getWritableDatabase(); long rowId = db.insert(tableName, null, values); // If the insert succeeded, the row ID exists. if (rowId > 0) { //Uri noteUri = ContentUris.withAppendedId(MainTable.CONTENT_ID_URI_BASE, rowId); Uri noteUri = ContentUris.withAppendedId(uri, rowId); getContext().getContentResolver().notifyChange(noteUri, null); return noteUri; } throw new SQLException("Failed to insert row into " + uri); } /** * Handle deleting data. */ @Override public int delete(Uri uri, String where, String[] whereArgs) { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); String finalWhere; int count; int id = mUriMatcher.match(uri); String tableName = hash_id_tableName.get(id); if (tableName != null){ if (isMain(id)){ count = db.delete(tableName, where, whereArgs); } else{ finalWhere = DatabaseUtilsCompat.concatenateWhere( getIdName(tableName) + " = " + ContentUris.parseId(uri), where); count = db.delete(tableName, finalWhere, whereArgs); } } else{ throw new IllegalArgumentException("Unknown URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } /** * Handle updating data. */ @Override public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int count; String finalWhere; int id = mUriMatcher.match(uri); String tableName = hash_id_tableName.get(id); if (tableName != null){ if (isMain(id)){ // If URI is main table, update uses incoming where clause and args. count = db.update(tableName, values, where, whereArgs); } else{ // If URI is for a particular row ID, update is based on incoming // data but modified to restrict to the given ID. finalWhere = DatabaseUtilsCompat.concatenateWhere( getIdName(tableName) + " = " + ContentUris.parseId(uri), where); count = db.update(tableName, values, finalWhere, whereArgs); } } else{ throw new IllegalArgumentException("Unknown URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } }
------- android培训、java培训、期待与您交流! ----------
切水果游戏非常流行哈。在学习box2d的时候了解到重力和施加外力这个内容的时候,突然就想到了切
水果是怎么写出来的。所以自己研究出了一个demon。
大概过程就是有一个小球过一会就从左下角抛出来,然后模拟在现实生活中自由落体的感觉,当然方向是不一样的,如果我的鼠标点中了小球,那么小球就会消失。让过程很简单,但是经过还是充满了探索,主要就是在删除小球的过程中,请仔细看到代码,我有注释。
首先写一个圆类:都是基本的知识,应该很容易理解。
public class MyCircle { //圆形的宽高与半径 float x, y, r; public MyCircle(float x, float y, float r) { this.x = x; this.y = y; this.r = r; } //设置圆形的X坐标 public void setX(float x) { this.x = x; } //设置半径的Y坐标 public void setY(float y) { this.y = y; } //绘制圆形 public void draw(Canvas canvas, Paint paint) { canvas.drawArc(new RectF(x, y, x + 2*r, y + 2*r), 0, 360, true, paint); } }
再看看surfaceView界面的代码:根据代码的注释很容易看懂。
public class MySurfaceView extends SurfaceView implements Callback, Runnable { private Thread th; private SurfaceHolder sfh; private Canvas canvas; private Paint paint; private boolean flag; // ----添加一个物理世界---->> final float RATE = 30;// 屏幕到现实世界的比例 30px:1m; World world;// 声明一个物理世界对象 AABB aabb;// 声明一个物理世界的范围对象 Vec2 gravity;// 声明一个重力向量对象 float timeStep = 1f / 60f;// 物理世界模拟的的频率 int iterations = 10;// 迭代值,迭代越大模拟越精确,但性能越低 // --->>给第一个Body赋予力 Body body1; int count=0;//计数器,没过多久就创造一个小球 //定义一个存放该被摧毁的body Vector<Object> Dbody=new Vector<Object>(); boolean Delete=false; public MySurfaceView(Context context) { super(context); this.setKeepScreenOn(true); sfh = this.getHolder(); sfh.addCallback(this); paint = new Paint(); paint.setAntiAlias(true); paint.setStyle(Style.STROKE); this.setFocusable(true); // --添加一个物理世界--->> aabb = new AABB();// 实例化物理世界的范围对象 gravity = new Vec2(0, 10);// 实例化物理世界重力向量对象 aabb.lowerBound.set(-100, -100);// 设置物理世界范围的左上角坐标 aabb.upperBound.set(100, 100);// 设置物理世界范围的右下角坐标 world = new World(aabb, gravity, true);// 实例化物理世界对象 } public void surfaceCreated(SurfaceHolder holder) { flag = true; th = new Thread(this); th.start(); } public Body createCircle(float x, float y, float r, boolean isStatic) { CircleDef cd = new CircleDef(); if (isStatic) { cd.density = 0; } else { cd.density = 1; } cd.friction = 0.8f; cd.restitution = 0.3f; cd.radius = r / RATE; BodyDef bd = new BodyDef(); bd.position.set((x + r) / RATE, (y + r) / RATE); Body body = world.createBody(bd); body.m_userData = new MyCircle(x, y, r); body.createShape(cd); body.setMassFromShapes(); return body; } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub Body body = world.getBodyList();//如果点击了,就判断点击的地方是否在小球内部,所以要取出所有小球,一个一个与点击的地方比对 for (int i = 1; i < world.getBodyCount(); i++) { float x=event.getX(); float x1=body.getPosition().x * RATE-10 ; float x2=body.getPosition().x * RATE+10; float y=event.getY(); float y1=body.getPosition().y * RATE-10; float y2=body.getPosition().y * RATE+10; // System.out.println(" x:"+x+" y:"+y+" body.getPosition().x:"+body.getPosition().x+" body.getPosition().y:"+body.getPosition().y if(x1<x&&x<x2&&y1<y&&y<y2) { Dbody.add(body); Delete=true; System.out.println("点准了"); } body = body.m_next; } return super.onTouchEvent(event); } public void myDraw() { try { canvas = sfh.lockCanvas(); if (canvas != null) { canvas.drawColor(Color.WHITE); Body body = world.getBodyList(); for (int i = 1; i < world.getBodyCount(); i++) { ((MyCircle) body.m_userData).draw(canvas, paint); body = body.m_next; } } } catch (Exception e) { Log.e("Himi", "myDraw is Error!"); } finally { if (canvas != null) sfh.unlockCanvasAndPost(canvas); } } public void Logic() { // --开始模拟物理世界--->> world.step(timeStep, iterations);// 物理世界进行模拟 if(Delete){//注意所有的删除body操作必须写在world.step的后面。并且要加入到一个集合里面去一次性删除。 System.out.println("开始删"); for(int j=0;j<Dbody.size();++j) { Body body2=(Body)Dbody.get(j); world.destroyBody(body2); System.out.println("删一个"); } Dbody.removeAllElements(); Delete=false; } ++count; if(count%80==0) { int i=(int)(Math.random()*100); body1 = createCircle(0, 450, 10, false); Vec2 vForce = new Vec2(i,-350); body1.applyForce(vForce, body1.getWorldCenter()); } // 取出body链表表头 Body body = world.getBodyList(); for (int i = 1; i < world.getBodyCount(); i++) { // 设置MyCircle的X,Y坐标 MyCircle mc = (MyCircle) body.m_userData; mc.setX(body.getPosition().x * RATE - mc.r); mc.setY(body.getPosition().y * RATE - mc.r); // 将链表指针指向下一个body元素 body = body.m_next; } } public void run() { while (flag) { myDraw(); Logic(); try { Thread.sleep((long) timeStep * 1000); } catch (Exception ex) { Log.e("Himi", "Thread is Error!"); } } } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } public void surfaceDestroyed(SurfaceHolder holder) { flag = false; } }
以及MainActivity.java的代码:注意设置全屏的效果,在很多地方很常用
public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //下两句还有显示全屏的代码 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(new MySurfaceView(this)); } }
最后来看一幅效果图
这是小球在空中的情景,我只要去点就可以让其消失。
我相信做到这一步,再接下来做一切扩展就比较容易了。
其实很是很开心的,很有成就感呀
------- android培训、java培训、期待与您交流! ----------
转:ubuntudaily.net/2011/11/how-to-install-google-input-method-in-ubuntu-1004