android开发经验笔记总计
时间:2023-05-03 17:37:00
四大组件:
Activity
AndroidRuntime: android.util.AndroidRuntimeException: Calling startActivity from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag .Is this really what you want?
3).singleTask:栈内复用模式。
只要是单实例模式Activity存在于一个栈中,启动这么多次Activity都不会重新创建实例,和singleTop一样,系统会回调其onNewIntent。当一个具有singleTask模式的Activity请求启动后,比如Activity A,系统首先会寻找是否存在A想要的任务栈,如果不存在,就重新创建一个任务栈,然后创建A的实例后把A放入栈中。如果存在A所需要的任务栈,这时就要看栈中的A的实例存在,如果实例存在,那么系统就会把A调到栈顶并调用它的onNewIntent方法,如果实例不存在,就创建A的事例并把A压入栈中。举例:
a.比如目前任务栈中S1的情况是ABC,这个时候Activity D以singleTask的,模式请求启动,其所需要的是任务栈S2,由于S2和D的实例都不存在,所以系统会先创建任务栈S2,然后再创建D的实例并将其入栈S2.
b.另外一种情况,假设D所需要的任务栈为S1,那么由于S1已经存在了,所以系统会直接创建D的实例,并将其入栈S1.
c.如果D所需要的任务栈为S1,此时S1的情况为ADBC,根据栈内复用的原则,此时D不会创建,系统会把D切换到栈顶并调用其onNewIntent方法,同时由于singleTask默认具有clearTop的效果,会导致栈内所有在D上面的Activity全部出栈,于是最终S1的情况为AD。
4).singleInstance:单实例模式。
加强版的singleTask模式,除了具备singleTask的所有特性外,还加强了一点,具有此模式的Activity只能单独位于一个任务栈中。
public class MyApp extends Application
{
private Bitmap mBitmap;
public Bitmap getBitmap()
{
return mBitmap;
}
public void setBitmap(Bitmap bitmap)
{
this.mBitmap = bitmap;
}
}
获得Bitmap对象的代码:
ImageView imageview = (ImageView)findViewById(R.id.ivImageView);
MyApp myApp = (MyApp)getApplication();
imageview.setImageBitmap(myApp.getBitmap());
上面的代码可以在任何Service和Activity中使用,全局的。 8.Activity的Task相关: http://blog.csdn.net/liuhe688/article/details/6761337
package com.example.result;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
public static final int REQUEST_CODE1 = 1;
public static final int REQUEST_CODE2 = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,
SecondActivity.class);
startActivityForResult(intent, REQUEST_CODE1);
}
});
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,
ThridActivity.class);
startActivityForResult(intent, REQUEST_CODE2);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE1) {
Toast.makeText(getApplicationContext(),
"111->" + data.getStringExtra("njj"), Toast.LENGTH_SHORT)
.show();
}
if (requestCode == REQUEST_CODE2) {
Toast.makeText(getApplicationContext(),
"222->" + data.getStringExtra("njj"), Toast.LENGTH_SHORT)
.show();
}
}
}
package com.example.result;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("njj", "niejianjian - second");
setResult(RESULT_OK, intent);
finish();
}
});
}
}
package com.example.result;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ThridActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_thrid);
Button button3 = (Button) findViewById(R.id.button3);
button3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("njj", "niejianjian - thrid");
setResult(RESULT_OK, intent);
finish();
}
});
}
}
BroadcastReceiver
Intent intent = new Intent();
intent.setAction("njj.test.receive");
sendBroadcast(intent);
IntentFilter filter = new IntentFilter();
filter.addAction("njj.test.receive"); // 添加actionyongyu匹配需要接受的广播
registerReceiver(receiver, filter); // receiver是一个广播对象。
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
}
};
取消绑定只需要执行
unregisterReceiver(receiver);
一般在onStart中注册,在onStop中取消解绑。
6.动态注册的广播,永远要快于静态注册的广播,不管静态注册的优先级设置有多高,不管动态注册的优先级有多低。因为代码中注册的运行在内存中,xml在系统中。
在一个按钮的点击事件中发送广播
Intent intent = new Intent();
intent.setAction("njj.test.receive");
intent.putExtra("key", "发送给receive1的广播");
sendOrderedBroadcast(intent, null);
public class MyReceive1 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("onreceive");
if (intent.getAction().equals("njj.test.receive")) {
Toast.makeText(context, intent.getStringExtra("key"),
Toast.LENGTH_SHORT).show();
Bundle bundle = new Bundle();
bundle.putString("re1", "有序广播");
setResultExtras(bundle);
// abortBroadcast(); // 终止传递
}
}
}
public class MyReceive2 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = getResultExtras(true);
String msg = bundle.getString("re1");
String msg2 = intent.getStringExtra("key");
System.out.println("msg -> " + msg);
System.out.println("msg2 -> " + msg2);
}
}
广播会先传递到优先级高的MyReceive1,然后在传递到MyReceive2,在MyReceive1中可以将广播终止传递,也可以传递给下一个接受者数据。
Service
package com.example.boradcasttest;
import android.app.Activity;
import android.app.IntentService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
MyConn myConn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myConn = new MyConn();
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("click ----> button1");
Intent intent = new Intent(MainActivity.this, MyService1.class);
startService(intent);
}
});
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("click ----> button2");
Intent intent = new Intent(MainActivity.this, MyService1.class);
stopService(intent);
}
});
Button button3 = (Button) findViewById(R.id.button3);
button3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("click ----> button3");
Intent intent = new Intent(MainActivity.this, MyService1.class);
bindService(intent, myConn, BIND_AUTO_CREATE);
}
});
Button button4 = (Button) findViewById(R.id.button4);
button4.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("click ----> button4");
unbindService(myConn);
}
});
Button button5 = (Button) findViewById(R.id.button5);
button5.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("click ----> button5");
Intent intent = new Intent();
intent.setAction("stop.service1");
sendBroadcast(intent);
}
});
}
private class MyConn implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder service) {
// 可以通过IBinder的对象 去使用service里面的方法
}
public void onServiceDisconnected(ComponentName name) {
}
}
}
package com.example.boradcasttest;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.IBinder;
public class MyService1 extends Service {
@Override
public IBinder onBind(Intent intent) {
System.out.println("MyService1 -> onBind");
return null;
}
@Override
public void onRebind(Intent intent) {
System.out.println("MyService1 -> onRebind");
super.onRebind(intent);
}
@Override
public boolean onUnbind(Intent intent) {
System.out.println("MyService1 -> onUnbind");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
System.out.println("MyService1 -> onCreate");
super.onCreate();
}
@Override
@Deprecated
public void onStart(Intent intent, int startId) {
System.out.println("MyService1 -> onStart");
IntentFilter filter = new IntentFilter();
filter.addAction("stop.service1");
registerReceiver(receiver, filter);
super.onStart(intent, startId);
}
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
System.out.println("MyService1 -> bindService");
return super.bindService(service, conn, flags);
}
@Override
public void unbindService(ServiceConnection conn) {
System.out.println("MyService1 -> unbindService");
super.unbindService(conn);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("MyService1 -> onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean stopService(Intent name) {
System.out.println("MyService1 -> stopService");
stopSelf(); // 停止服务
return super.stopService(name);
}
@Override
public void onDestroy() {
System.out.println("MyService1 -> onDestroy");
super.onDestroy();
}
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("MyService1 -> receiver");
if (intent.getAction().equals("stop.service1")) {
context.stopService(intent);
}
}
};
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification noti = new Notification.Builder(this)
.setContentTitle("Title")
.setContentText("Message")
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendingIntent)
.build();
startForeground(12346, noti);
return Service.START_STICKY;
}
public class MyService extends Service {
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
//经测试,Service里面是不能进行耗时的操作的,必须要手动开启一个工作线程来处理耗时操作
System.out.println("onStart");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("睡眠结束");
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class MyIntentService extends IntentService {
public MyIntentService() {
super("yyyyyyyyyyy");
}
@Override
protected void onHandleIntent(Intent intent) {
// 经测试,IntentService里面是可以进行耗时的操作的
//IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent
//对于异步的startService请求,IntentService会处理完成一个之后再处理第二个
System.out.println("onStart");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("睡眠结束");
}
}
public class ServiceDemoActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startService(new Intent(this,MyService.class));//主界面阻塞,最终会出现Application not responding
//连续两次启动IntentService,会发现应用程序不会阻塞,而且最重的是第二次的请求会再第一个请求结束之后运行(这个证实了IntentService采用单独的线程每次只从队列中拿出一个请求进行处理)
startService(new Intent(this,MyIntentService.class));
startService(new Intent(this,MyIntentService.class));
}
}
IntentServicede 的好处:
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}
如果需要重写其他回调方法,如onCreate,onStartCommand()等,一定要调用super()方法,保证intentservice正确处理worker线程,只有onHandleIntent()和onBind()不需要这样,如:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
Service对象不能自己启动,需要通过某个Activity、Service或者其他Context对象来启动,启动的方法有两种,Context.startService()和Context.bindService()。两种方式的生命周期是不同的。
context.startService:
如果service还没有运行,则android先调用onCreate()方法,然后调用onStart();如果service已经运行,则至调用onStart(),所以一个service的onStart()方法可能会重复调用多次。stopService的时候会直接调用onDestory(),如果是调用者自己直接退出而没有调用stopService的话,service会一直在后台运行,该service的调用者再次启动起来后可以通过stopService关闭service
1.在同一个应用任何地方调用startService()方法就能启动Service了,然后系统会回调service类的onCreate()以及onStart()方法,这样启动的service会一直运行在后台,知道Context.stopService()或者selfStop()方法被调用。
2.另外一种bindService()方法的意思是,把这个Service和调用service的客户类绑起来,如果调用这个客户类被销毁,service也会被销毁,用这个方法的一个好处是,bindService()方法执行后service会回调上边提到的onBind()方法,你可以从这里返回一个实现了IBind接口的类,在额客户端操作这个类就能和这个服务通信了, 比如得到service运行的状态或其他操作,如果service还没有运行,使用这个方法启动service就会onCreate()方法而不会调用onStart().
3.startService()的目的是回调onStart()方法,onCreate()方法是在Service不存在的时候调用的,如果Service存在(例如之前调用了bindService,那么Service的onCreate方法已经被调用了)那么startService()将跳过onCreate()方法。
4.bindService()目的是回调onBind()方法,它的作用是在Service和调用者之间建立一个桥梁,并不负责更多的工作(例如一个service需要连接服务器的操作),一般使用bindService来帮顶到一个现有的Service(即通过StartService启动的服务)
由于Service的onStart()方法只有在startService()启动service的情况下才会调用,故使用onStart()的时候要注意这点。
5.与Service通信并且让它持续运行:如果我们想要保持和Service的通信,又不想让Service随着Activity退出而退出。你可以先startService()然后在bindService()。当你不需要帮顶的时候就执行unbindService()方法,执行这个方法只会触发Service的onUnbind()方法而不会把这个Service销毁,这样就可以既保持和service的通信,也不会随着activity销毁而销毁。
6.为什么是foregorund:默认启动的Service是被标记为background,当前运行的Activity一般被标记为foreground,也就是说你给service设置了foreground那么他就和正在运行的Activity类似优先级得到了一定的提高。当让这并不能保证你service永远不被杀掉。只是提高了他的优先级
7.如果先是bind了,那么start的时候就直接运行service的onStart方法,如果是先start,那么bind的时候就直接运行onBind方法,如果你先bind上了,就stop不掉了,只能先执行UnbindService,再stopService,所以是先start还是先bind行为是有区别的。
8.如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()。如果调用startService()方法前服务已经被创建,多次调用startService()方法,并不会导致多次创建服务,但会导致多次调用onStart()方法,采用startService()方法启动的服务只能调用Context.stopService()方法结束服务,服务结束时会被调用onDestory()。
9.如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法,这个时候调用者和服务绑定在一起,调用者退出,系统就会先调用服务的onUnbind()方法,接着调用onDestory()方法,如果调用bindService()方法前服务已经被绑定,多次调用bindService()并不会导致多次创建服务及绑定(也就是说onCreate和onBind方法并不会多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法。
10.Service和Thread的区别:
Thread是程序执行的最小单位,他是分配CPUde基本但那位,可以用Thread来执行一些异步的操作。
Service是android的一种机制,当它运行的时候,如果是Local Service,那么对应的Service是运行在主进程的main线程上的。如onCreate,onStart这些函数在被系统调用的时候都是在主进程的main线程上运行的。如果Remote Service,那么对应的Service则是运行在独立进程的main线程上,因此不要把Service理解成线程,它和线程半毛钱关系都没有。
那么我们为什么要用Service? Thread的运行是独立于Activity的,也就是说当一个Activity被finish之后,如果你没有主动停止Thread或者Thread中的run方法没有执行完毕,Thread也会一直执行。因此这里会出现一个问题,当Activity被finish掉之后,你不在持有该Thread的引用,另一方面,你没有办法在不同的Activity中对同一个Thread进行控制。
举个例子:如果你的Thread需要不停的隔一段时间就要连接服务器做某种同步的话,该Thread需要在Activity没有start的时候就运行。这个时候当你start一个Activity就没有办法在该Activity里面控制之前创建的Thread。因此你需要创建并启动一个Service。在Service里面创建、运行并控制该Thread,这样便解决了该问题(因为任何Activity都可以控制同一个Service,而系统也只会创建一个对应的Service实例)
因此你可以把Service想象成一种消息服务,而你可以在任何有Context的地方调用StartService、Context.stopService、Context.bindService、Context.unbindService,来控制它,你也可以在Service中注册BroadcastReceiver,在其他地方通过发送broadcast来控制它,当然这些都是Thread做不到的。