先说使用,再给定义
使用方法:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"ImageCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithFrame:CGRectZero reuseIdentifier:CellIdentifier]
autorelease];
} else {
AsyncImageView* oldImage = (AsyncImageView*)
[cell.contentView viewWithTag:999];
[oldImage removeFromSuperview];
}
CGRect frame;
frame.size.width=75; frame.size.height=75;
frame.origin.x=0; frame.origin.y=0;
AsyncImageView* asyncImage = [[[AsyncImageView alloc]
initWithFrame:frame] autorelease];
asyncImage.tag = 999;
NSURL *url = [NSURL URLWithString: @"image url"];
[asyncImage loadImageFromURL:url];
[cell.contentView addSubview:asyncImage];
return cell;
}
类的定义:
.h
#import <UIKit/UIKit.h>
@interface AsyncImageView : UIView {
//could instead be a subclass of UIImageView instead of UIView, depending on what other features you want to
// to build into this class?
NSURLConnection* connection; //keep a reference to the connection so we can cancel download in dealloc
NSMutableData* data; //keep reference to the data so we can collect it as it downloads
//but where is the UIImage reference? We keep it in self.subviews - no need to re-code what we have in the parent class
}
- (void)loadImageFromURL:(NSURL*)url;
- (UIImage*) image;
@end
.m
#import "AsyncImageView.h"
@implementation AsyncImageView
- (void)loadImageFromURL:(NSURL*)url {
if (connection!=nil) { [connection release]; }
if (data!=nil) { [data release]; }
NSURLRequest* request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
connection = [[NSURLConnection alloc]
initWithRequest:request delegate:self];
//TODO error handling, what if connection is nil?
}
- (void)connection:(NSURLConnection *)theConnection
didReceiveData:(NSData *)incrementalData {
if (data==nil) {
data =
[[NSMutableData alloc] initWithCapacity:2048];
}
[data appendData:incrementalData];
}
- (void)connectionDidFinishLoading:(NSURLConnection*)theConnection {
[connection release];
connection=nil;
if ([[self subviews] count]>0) {
[[[self subviews] objectAtIndex:0] removeFromSuperview];
}
UIImageView* imageView = [[[UIImageView alloc] initWithImage:[UIImage imageWithData:data]] autorelease];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth || UIViewAutoresizingFlexibleHeight );
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout];
[self setNeedsLayout];
[data release];
data=nil;
}
- (UIImage*) image {
UIImageView* iv = [[self subviews] objectAtIndex:0];
return [iv image];
}
- (void)dealloc {
[connection cancel];
[connection release];
[data release];
[super dealloc];
}
@end
原文地址:http://www.markj.net/iphone-asynchronous-table-image/
在android原生的关机流程里面是没有声音和 自定义动画的借口,因此为了实现这两个功能需要找到相应的地方并采用合适的方式进行处理。
在关机的ShutdownThread类里面有两个很重要的方法,一个是beginShutdownSequence,解析如下:
private static void beginShutdownSequence(Context context) {
synchronized (sIsStartedGuard) {
sIsStarted = true;
}
// throw up an indeterminate system dialog to indicate radio is
// shutting down.
//动画开始
//这里也是可以加入声音的播放流程,(这里要考虑到几点:声音与动画的同步;需要避免蓝牙等断开操作导致的声音不连续)
ProgressDialog pd = new ProgressDialog(context);
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
pd.setIndeterminate(true);
pd.setCancelable(false);
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
if (!context.getResources().getBoolean(
com.android.internal.R.bool.config_sf_slowBlur)) {
pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
}
pd.show();
//动画结束,需要在这里加入自定的view并进行显示。这里的view需要注意横竖屏的转化,让其显示唯一,后面的代码则是启动关机的动作。
// start the thread that initiates shutdown
sInstance.mContext = context;
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
sInstance.mWakeLock = null;
if (sInstance.mPowerManager.isScreenOn()) {
try {
sInstance.mWakeLock = sInstance.mPowerManager.newWakeLock(
PowerManager.FULL_WAKE_LOCK, "Shutdown");
sInstance.mWakeLock.acquire();
} catch (SecurityException e) {
Log.w(TAG, "No permission to acquire wake lock", e);
sInstance.mWakeLock = null;
}
}
sInstance.mHandler = new Handler() {
};
sInstance.start();
}
第二个就是run方法,该方法决定了一个完整的关机流程所需要的时间。设置时间为最少10秒,其实该段代码在无声音和动画的情况下可以在5秒内执行完毕。如果考虑到声音就要注意了,因为很有可能产生破音(就是关机的最后一刻会产生比较尖锐的声音)
public void run() {
boolean bluetoothOff;
boolean radioOff;
BroadcastReceiver br = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
// We don't allow apps to cancel this, so ignore the result.
actionDone();
}
};
Log.i(TAG, "Sending shutdown broadcast...");
// First send the high-level shut down broadcast.
mActionDone = false;
mContext.sendOrderedBroadcast(new Intent(Intent.ACTION_SHUTDOWN), null,
br, mHandler, 0, null, null);
//从这里开始
final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
synchronized (mActionDoneSync) {
while (!mActionDone) {
long delay = endTime - SystemClock.elapsedRealtime();
if (delay <= 0) {
Log.w(TAG, "Shutdown broadcast timed out");
break;
}
try {
mActionDoneSync.wait(delay);
} catch (InterruptedException e) {
}
}
}
//到这里结束,这段时间的延迟是可以缩短的,当然是会有些问题。当然如果是为了更快的关机,这些问题就可以通过动画和声音避免掉。
Log.i(TAG, "Shutting down activity manager...");
final IActivityManager am =
ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
if (am != null) {
try {
am.shutdown(MAX_BROADCAST_TIME);
} catch (RemoteException e) {
}
}
//从这里开始
final ITelephony phone =
ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
final IBluetooth bluetooth =
IBluetooth.Stub.asInterface(ServiceManager.checkService(
BluetoothAdapter.BLUETOOTH_SERVICE));
final IMountService mount =
IMountService.Stub.asInterface(
ServiceManager.checkService("mount"));
//到这里结束,可以通过以上的方式得到一只运行在后台的系统服务。蓝牙耳机也就是通过这种方式获取,然后再判断声音如何播放
try {
bluetoothOff = bluetooth == null ||
bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF;
if (!bluetoothOff) {
Log.w(TAG, "Disabling Bluetooth...");
bluetooth.disable(false); // disable but don't persist new state
}
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
bluetoothOff = true;
}
//
try {
radioOff = phone == null || !phone.isRadioOn();
if (!radioOff) {
Log.w(TAG, "Turning off radio...");
phone.setRadio(false);
}
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException during radio shutdown", ex);
radioOff = true;
}
Log.i(TAG, "Waiting for Bluetooth and Radio...");
// Wait a max of 32 seconds for clean shutdown
for (int i = 0; i < MAX_NUM_PHONE_STATE_READS; i++) {
if (!bluetoothOff) {
try {
bluetoothOff =
bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF;
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
bluetoothOff = true;
}
}
if (!radioOff) {
try {
radioOff = !phone.isRadioOn();
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException during radio shutdown", ex);
radioOff = true;
}
}
if (radioOff && bluetoothOff) {
Log.i(TAG, "Radio and Bluetooth shutdown complete.");
break;
}
SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
}
// Shutdown MountService to ensure media is in a safe state
IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
public void onShutDownComplete(int statusCode) throws RemoteException {
Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown");
actionDone();
}
};
Log.i(TAG, "Shutting down MountService");
// Set initial variables and time out time.
mActionDone = false;
final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME;
synchronized (mActionDoneSync) {
try {
if (mount != null) {
mount.shutdown(observer);
} else {
Log.w(TAG, "MountService unavailable for shutdown");
}
} catch (Exception e) {
Log.e(TAG, "Exception during MountService shutdown", e);
}
while (!mActionDone) {
long delay = endShutTime - SystemClock.elapsedRealtime();
if (delay <= 0) {
Log.w(TAG, "Shutdown wait timed out");
break;
}
try {
mActionDoneSync.wait(delay);
} catch (InterruptedException e) {
}
}
}
if (mReboot) {
Log.i(TAG, "Rebooting, reason: " + mRebootReason);
try {
Power.reboot(mRebootReason);
} catch (Exception e) {
Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);
}
} else if (SHUTDOWN_VIBRATE_MS > 0) {
// vibrate before shutting down
Vibrator vibrator = new Vibrator();
vibrator.vibrate(SHUTDOWN_VIBRATE_MS);
// vibrator is asynchronous so we need to wait to avoid shutting down too soon.
try {
Thread.sleep(SHUTDOWN_VIBRATE_MS);
} catch (InterruptedException e) {
}
}
//最后在这里一定要注意,声音是否播放完毕。如果没有完毕则要延时后再执行下面的命令,否则会产生破音。
// Shutdown power
Log.i(TAG, "Performing low-level shutdown...");
Power.shutdown();
}
run方法的整个关机过程包括上面的方法不能产生任何错误,即便是try catch处理过也不行,这样会导致机器调用reboot的命令,很无奈的!! 例如Thread.sleep就有可能产生错误,源码中就有这样的隐患。建议使用SystemClock.sleep替换,这样就可以避免机器重启的隐患。
XT702我家里的电脑,之前只要用数据线连上就可以读内存卡了
现在插上数据线后就一直有个MTP Device在那显示发现新硬件,然后手机就一直响
拿到单位的电脑用数据线连接一切正常,一回到家还是这样,两天了,新的驱动也装了,没有用,但是把USB调试模式打开就可以读内存卡了,以前还能连,现在怎么不行了,也并不是没有选择仅充电等选项
然后记起来上两天更新了windows media player11,用360给卸掉了 ,把从摩托官网下的驱动也给删除了,恢复到了windows media player10,这次不那么狂响了,但是一插上数据线就出现一个mtp media player的对话框,说:你想让windows做什么?按哪个都不能同步。
问题的原因就是在于自动、安装desktop的时候,电脑“识别”错了,一直出现那个mtp media player的对话框。去设备管理器里,找到XT702,右键更新驱动程序,不要选择自动,选择自动的话他又帮你安装MTP的驱动去了,手动找到装palm desktop的文件夹里的usbdriver,手动跟新下驱动就行了。电脑就认了。
更新驱动程序->从列表或指定位置安装(高级)->不要搜索,我要自己选择要安装的驱动程序,然后下一步就看到有一个MTP和一个USB的驱动,选择那个USB的驱动,然后下一步安装就可以了
黑色头发:http://heisetoufa.iteye.com/