精华内容
下载资源
问答
  • 上一篇文章:Android中程序与Service交互方式——综述 简述了Service的一些基础知识以及Service和Thread的简单区别,本文将着重讲解与Service交互的五种基本方式:广播交互、共享文件交互、Mssenger(信使)交互、...
    上一篇文章:Android中程序与Service交互的方式——综述 简述了Service的一些基础知识以及Service和Thread的简单区别,本文将着重讲解与Service交互的五种基本方式:广播交互、共享文件交互、Mssenger(信使)交互、自定义接口交互、AIDL交互。
    

           1. 广播交互

           提到Activity与Service的交互,可能狠多人首先想到的就是BroadCast——广播。在Android中,广播是系统提供的一种很好的交互方式。比如:在电池电量过低,开机完成等情况下,系统都会发出相应的系统广播,我们的应用程序只需要注册相应的广播接收器,就可以接收到这些系统的广播。同时,我们也可以定义自己的广播,这样在不同的Activity、Service以及应用程序之间,就可以通过广播来实现交互。我们通过模拟应用程序后台下载的情况来分析Service与Activity的交互方式。实现效果如图1.1:

    图1.1

            当我们点击StartService按钮之后,界面上的进度条将会每隔一秒加1。因为是模拟下载,因此下载动作我们在Service中通过一个Timer定时器来实现,在Timer中对一个整型数据i进行自加(i++),然后Client端获取Server端的i值并显示在界面上,从而达到模拟的目的。

            1.1. 实现原理

            Server端将目前的下载进度,通过广播的方式发送出来,Client端注册此广播的监听器,当获取到该广播后,将广播中当前的下载进度解析出来并更新到界面上。

            1.2. 实现步骤

            1.2.1 在Client端中通过startService()啟动Service。

    [java] view plaincopy
    1. if(v == startBtn){  
    2.     Log.i(TAG, "start button clicked...pid: "+Process.myPid());  
    3.     mIntent.setClass(BroadCastService.this, DownLoadService.class);  
    4.     startService(mIntent);  
    5. }  
              这里的mIntent = new Intent();Process.myPid()方法可以获取当前进程的ID号。
           1.2.2 DownLoadService接到启动的命令之后,执行onCreate()方法,并在其中开启timer计数模拟下载。

    [java] view plaincopy
    1. @Override  
    2. public void onCreate() {  
    3.     super.onCreate();  
    4.     Log.i(TAG, "DownLoadService.onCreate()...pid: "+Process.myPid());  
    5.     intent = new Intent("com.seven.broadcast");  
    6.     mTimer = new Timer();  
    7.     mTimer.schedule(new MyTimerTask(), 0 , TIME * 1000);  
    8. }  
              这里的intent是Server端向Client端传送数据用的,使用的action是”com.seven.broadcast”,Client端只有註册了相应action才能够接收到Server端的广播,并解析其中的内容。Process.myPid()是获取当前进程的ID。
            1.2.3 在Server端的timer计数其中发送广播,告知Client端目前下载进度。

    [java] view plaincopy
    1. class MyTimerTask extends TimerTask{  
    2.     @Override  
    3.     public void run() {  
    4.         if(i==100){  
    5.             i=0;  
    6.         }  
    7.         intent.putExtra("CurrentLoading", i);  
    8.         sendBroadcast(intent);  
    9.         i++;  
    10.         Log.e(TAG, "i= "+i);  
    11.     }  
    12. }  
              通过intent.putExtra(key,value);设置intent的值,然后通过sendBroadcast(intent)2方法,将广播发送出去。

           1.2.4 在Client端通过匿名内部类的方式实例化BroadcastReceiver并覆写其中的onReceive()方法。

    [java] view plaincopy
    1. BroadcastReceiver receiver = new BroadcastReceiver() {  
    2.     @Override  
    3.     public void onReceive(Context context, Intent intent) {  
    4.         if(MYACTION.equals(intent.getAction())){  
    5.             Log.i(TAG, "get the broadcast from DownLoadService...");  
    6.             curLoad = intent.getIntExtra("CurrentLoading", ERROR);  
    7.             mHandler.sendMessage(mHandler.obtainMessage());  
    8.         }  
    9.     }  
    10. };  
              在onReceive()方法中,判断是否为Server端发送的广播,如果是则对广播中携带的intent数据进行解包处理。这裡也可以单独写一个类继承自BroadcastReceiver,在其中覆写onReceive()方法,在Client端中实例化其对象,同样可以达到相应的效果,这样做可以为后面实现静态注册广播。
            1.2.5 更新主介面下载进度。

    [java] view plaincopy
    1. Handler mHandler = new Handler(){  
    2.     @Override  
    3.     public void handleMessage(Message msg) {  
    4.         super.handleMessage(msg);  
    5.         Log.i(TAG, "current loading: "+curLoad);  
    6.         if(curLoad<0||curLoad>100){  
    7.             Log.e(TAG, "ERROR: "+curLoad);  
    8.             return;  
    9.         }  
    10.         mProgressBar.setProgress(curLoad);  
    11.         mTextView.setText(curLoad+"%");  
    12.     }  
    13. };  
                 这里对获取到的进度进行了一次判断,如果获取到的值没有异常,那么将会显示到界面,并更新进度条的进度,如果异常则返回。
             1.2.6 一定要对Broadcast进行注册和取消注册。只有注册之后相应的broadcast之后才能接收到广播注册方法有两种。
             动态注册/取消注册:

    [java] view plaincopy
    1. @Override  
    2. protected void onResume() {  
    3.     super.onResume();  
    4.     Log.i(TAG, "register the broadcast receiver...");  
    5.     IntentFilter filter = new IntentFilter();  
    6.     filter.addAction(MYACTION);  
    7.     registerReceiver(receiver, filter);  
    8. }  
    9. @Override  
    10. protected void onDestroy() {  
    11.     super.onDestroy();  
    12.     Log.i(TAG, "unregister the broadcast receiver...");  
    13.     unregisterReceiver(receiver);  
    14. }  
               动态註册可以随时註册随时取消。

            静态註册:

    [html] view plaincopy
    1. <receiver android:name="MyBroadcastReceiver">  
    2.     <intent-filter>  
    3.         <action android:name="com.seven.broadcast" />  
    4.     </intent-filter>  
    5. </receiver>  
               注:这里的MyBroadcastReceiver是一个继承自BroadcastReceiver的类。静态注册只要注册了一次那么只要该程序没有被卸载那么该广播将一直有效。

            最后贴出整个AndroidManifest.xml文件

    [html] view plaincopy
    1. <application android:icon="@drawable/icon" android:label="@string/app_name">  
    2.     <activity android:name=".BroadCastService"  
    3.               android:label="@string/app_name">  
    4.         <intent-filter>  
    5.             <action android:name="android.intent.action.MAIN" />  
    6.             <category android:name="android.intent.category.LAUNCHER" />  
    7.         </intent-filter>  
    8.     </activity>  
    9.     <service android:name="DownLoadService" android:process=":remote"/>  
    10. </application>  
              这里的android:process =”:remote”可以使该Service运行在单独进程中,从而可以模拟跨进程通信。

           1.3 小结

           通过广播的方式实现Activity与Service的交互操作简单且容易实现,可以胜任简单级的应用。但缺点也十分明显,发送广播受到系统制约。系统会优先发送系统级广播,在某些特定的情况下,我们自定义的广播可能会延迟。同时在广播接收器中不能处理长耗时操作,否则系统会出现ANR即应用程序无响应。

            2. 共享文件交互

            这里提到的共享文件指的是Activity和Service使用同一个文件来达到传递数据的目的。我们使用SharedPreferences来实现共享,当然也可以使用其它IO方法实现,通过这种方式实现交互时需要注意,对于文件的读写的时候,同一时间只能一方读一方写,不能两方同时写。实现效果如图2.1:

    图2.1

             2.1 实现原理

             Server端将当前下载进度写入共享文件中,Client端通过读取共享文件中的下载进度,并更新到主界面上。

             2.2 实现步骤

             2.2.1 在Client端通过startService()啟动Service。

    [java] view plaincopy
    1. if(startSerBtn==v){  
    2.     Log.i(TAG, "Start Button Clicked.");  
    3.     if(intent!=null){  
    4.     startService(intent);  
    5.     timer.schedule(new MyTimerTask(), 0, TIME * 1000);  
    6.     }  
    7. }  
              这里的intent = new Intent()2只是为了启动Server端。
            2.2.2 Server端收到启动intent之后执行onCreate()方法,并开启timer,模拟下载,以及初始化SharedPreferences对象preferences。

    [java] view plaincopy
    1. @Override  
    2. public void onCreate() {  
    3.     super.onCreate();  
    4.     Log.i(TAG, "DownLoadService.onCreate()...");  
    5.     preferences = getSharedPreferences("CurrentLoading_SharedPs"0);  
    6.     timer = new Timer();  
    7.     timer.schedule(new MyTimerTask(), 0, TIME*1000);  
    8. }  
              通过preferences=getSharedPreferences(String,MODE)2可以在/data/data/com.seven.servicetestdemo/shared_prefs文件夹下建立相应的xml文件。

           2.2.3 开始计数并将下载进度写入shared_prefs文件夹下的xml文件中,内容以键值对的方式保存。

    [java] view plaincopy
    1. class MyTimerTask extends TimerTask{  
    2.     @Override  
    3.     public void run() {  
    4.         setCurrentLoading();  
    5.         if(100==i){  
    6.             i=0;  
    7.         }  
    8.         i++;  
    9.     }         
    10. }     
    11. private void setCurrentLoading() {  
    12.     preferences.edit().putInt("CurrentLoading", i).commit();  
    13. }  
               对於SharedPreferences的使用需要注意一下几点:

            首先,使用sharedPreferences前需要获取文件引用。

            preferences = getSharedPreferences("CurrentLoading_SharedPs", 0);

            其次,使用sharedpreferences写数据方式。

            preferences.edit().putInt("CurrentLoading", i).commit();

            最后,读取数据的方式。

            int couLoad = preferences.getInt("CurrentLoading", 0);

            2.2.4 Client端通过读取/data/data/com.seven.servicetestdemo/shared_prefs文件夹下的xml文件,并取得里面的键值对,从而获取到当前的下载进度,并更新到主界面上。

    [java] view plaincopy
    1. Handler mHandler = new Handler(){  
    2.     @Override  
    3.     public void handleMessage(Message msg) {  
    4.         super.handleMessage(msg);  
    5.         int couLoad = preferences.getInt("CurrentLoading"0);  
    6.         mProgressBar.setProgress(couLoad);  
    7.         currentTv.setText(couLoad+"%");  
    8.     }  
    9.  };  

              2.3 小结

            因為方法简单,因此就不贴出AndroidManifest.xml文件了。对於这种方式实现Activity与Service的交互,可以说很方便,就像使用管道,一个往裡写,一个往外读。但这种方式也有缺陷,写入数据较为复杂以及数据量较大时,就有可能导致写入与读数据出不一致的错误。同时因为经过了一个中转站,这种操作将更耗时。

            3. Messenger交互(信使交互)

            Messenger翻译过来指的是信使,它引用了一个Handler对象,别人能够向它发送消息(使用mMessenger.send(Message msg)方法)。该类允许跨进程间基于Message通信,在服务端使用Handler创建一个 Messenger,客户端只要获得这个服务端的Messenger对象就可以与服务端通信了。也就是说我们可以把Messenger当做Client端与Server端的传话筒,这样就可以沟通交流了。实现效果如图3.1:

    图3.1

            3.1 实现原理

            在Server端与Client端之间通过一个Messenger对象来传递消息,该对象类似于信息中转站,所有信息通过该对象携带。

            3.2 Messenger的一般用法

            (1). 在Server端创建信使对象。

                   mMessenger = new Messenger(mHandler)

            (2). Client端使用bindService()绑定Server端。

            (3). Server端的onBind()方法返回一个binder对象。

                   return mMessenger.getBinder();

            (4). Client端使用返回的binder对象得到Server端信使。

    [java] view plaincopy
    1. public void onServiceConnected(ComponentName name, IBinder service) {    
    2.               rMessenger = new Messenger(service);        
    3.              ......  
    4.  }  
              这里虽然是new了一个Messenger,但我们查看它的实现

    [java] view plaincopy
    1. public Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target);  }   
               发现它的mTarget是通过AIDL得到的,实际上就是远程创建的那个。

            (5). Client端可以使用这个Server端的信使对象向Server端发送消息。
                   rMessenger.send(msg);

            这样Server端的Handler对象就能收到消息了,然后可以在其handlerMessage(Message msg)方法中进行处理。经过这5个步骤之后只有Client端向Server端发送消息,这样的消息传递是单向的,那么如何实现消息的双向传递呢?

            首先需要在第5步做修改,在send(msg)前通过msm.replyTo = mMessenger将Client端自己的信使设置到消息中,这样Server端接收到消息时同时也得到了Client端的信使对象,然后Server端也可以通过使用得到的Client端的信使对象来项Client端发送消息 cMessenger = msg.replyTo2  cMessenger.send(message);

           这样即完成了从Server端向Client端发送消息的功能,这样Client端可以在自己的Handler对象的handlerMessage()方法中接收服务端发送来的message进行处理。

            3.3 实现步骤

            3.3.1 创建并初始化Server端的信使对象。

    [java] view plaincopy
    1. private Handler mHandler = new Handler(){  
    2.     @Override  
    3.     public void handleMessage(Message msg) {  
    4.         super.handleMessage(msg);  
    5.         switch (msg.what) {  
    6.         case TEST:  
    7.             Log.e(TAG, "Get Message from MainActivity.");  
    8.             cMessenger = msg.replyTo;  
    9.             mTimer.schedule(new MyTimerTask(), 1000,TIME * 1000);  
    10.             break;  
    11.             default:  
    12.                 break;  
    13.             }  
    14.         }         
    15. };  
    16. //It's the messenger of server  
    17. private Messenger mMessenger = new Messenger(mHandler);  

              3.3.2 在Client端使用bindService()方法绑定Server端。

    [java] view plaincopy
    1. private void doBindService(){  
    2.         Log.i(TAG, "doBindService()...");  
    3.     mIsBind = bindService(intent, serConn, BIND_AUTO_CREATE);//if bind success return true  
    4.         Log.e(TAG, "Is bind: "+mIsBind);  
    5. }  

              3.3.3 在Server端的onBind()方法中返回一个binder对象。

    [java] view plaincopy
    1. @Override  
    2. public IBinder onBind(Intent intent) {  
    3.     Log.i(TAG, "MessengerService.onBind()...");  
    4.     return mMessenger.getBinder();  
    5. }  
              这裡的mMessenger就是Server端的信使对象。

            3.3.4 Client端使用ServiceConnected()方法来获取Server端的信使对象。

    [java] view plaincopy
    1. private ServiceConnection serConn = new ServiceConnection() {     
    2.     @Override  
    3.     public void onServiceDisconnected(ComponentName name) {  
    4.         Log.i(TAG, "onServiceDisconnected()...");  
    5.         rMessenger = null;  
    6.     }         
    7.     @Override  
    8.     public void onServiceConnected(ComponentName name, IBinder service) {  
    9.         Log.i(TAG, "onServiceConnected()...");  
    10.     rMessenger = new Messenger(service);//get the object of remote service  
    11.     mMessenger = new Messenger(mHandler);//initial the object of local service  
    12.     sendMessage();  
    13.     }  
    14. };  
               获取Server端的信使对象的同时,也初始化Client端的自己的信使对象,并且通过sendMessage()方法发送消息给Server端,表示可以开始下载了。

            3.3.5 Client端使用获取到的rMessenger来发送消息给Server端,同时将Client端的信使封装到消息中,一并发送给Server端。

    [java] view plaincopy
    1. private void sendMessage() {  
    2.     Message msg = Message.obtain(null, MessengerService.TEST);//MessengerService.TEST=0  
    3.     msg.replyTo = mMessenger;  
    4.     try {  
    5.         rMessenger.send(msg);  
    6.     } catch (RemoteException e) {  
    7.         e.printStackTrace();  
    8.     }  
    9. }  
               这里的MessengerService.TEST為Server端里的一个静态常量。Msg.replyTo=mMessenger;表示发送给Server端的信息里携带Client端的信使。

            3.3.6 Server端获取Client端发送的消息并得到Client端的信使对象。

    [java] view plaincopy
    1. private Handler mHandler = new Handler(){  
    2.     @Override  
    3.     public void handleMessage(Message msg) {  
    4.         super.handleMessage(msg);  
    5.         switch (msg.what) {  
    6.         case TEST:  
    7.             Log.e(TAG, "Get Message from MainActivity.");  
    8.             cMessenger = msg.replyTo;//get the messenger of client  
    9.             mTimer.schedule(new MyTimerTask(), 1000,TIME * 1000);  
    10.             break;  
    11.         default:  
    12.             break;  
    13.         }  
    14.     }  
    15. };  
               在接收到Client端的信息之后,Server端开啟timer模拟下载,并接收Client端的信使对象。

            3.3.7 Server端向Client端发送数据。

    [java] view plaincopy
    1. class MyTimerTask extends TimerTask {  
    2.     @Override  
    3.     public void run() {  
    4.         if (i == 100) {  
    5.             i = 0;  
    6.         }  
    7.         try {  
    8.             //send the message to the client  
    9.         Message message = Message.obtain(null, MessengerService.TEST,i, 0);  
    10.             cMessenger.send(message);  
    11.         } catch (RemoteException e) {  
    12.                 e.printStackTrace();  
    13.         }  
    14.             i++;  
    15.     }  
    16. }  
              直接使用接收到的Client端的信使对象来发送当前下载进度给Client端。

            3.3.8 Client端接收来自Server端的数据。


    [java] view plaincopy
    1. private Handler mHandler = new Handler(){  
    2.     @Override  
    3.     public void handleMessage(Message msg) {  
    4.         super.handleMessage(msg);  
    5.         switch (msg.what) {  
    6.         case MessengerService.TEST:  
    7.             Log.e(TAG, "Get Message From MessengerService. i= "+msg.arg1);  
    8.             int curLoad = msg.arg1;  
    9.             mTextView.setText(curLoad+"%");  
    10.             mProgressBar.setProgress(curLoad);  
    11.             break;  
    12.         default:  
    13.             break;  
    14.         }  
    15.     }  
    16. };  
               Client端的接收和Server端的接收狠类似。接收到Server端传过来的数据之后进行介面更新,以及下载进度更新。

            以下是AndroidManifest.xml文件:

    [html] view plaincopy
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    3.       package="com.seven.messengerservicedemo"  
    4.       android:versionCode="1"  
    5.       android:versionName="1.0">  
    6.     <uses-sdk android:minSdkVersion="10" />  
    7.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
    8.         <activity android:name=".MainActivity"  
    9.                   android:label="@string/app_name">  
    10.             <intent-filter>  
    11.                 <action android:name="android.intent.action.MAIN" />  
    12.                 <category android:name="android.intent.category.LAUNCHER" />  
    13.             </intent-filter>  
    14.         </activity>  
    15.     <service android:name="MessengerService">  
    16.         <intent-filter>  
    17.     <action ndroid:name="com.seven.messagerservice.MessengerService" />  
    18.         </intent-filter>  
    19.     </service>  
    20. </application>  
    21. </manifest>  
               这里在Service的註册中加入了过滤动作,只有相匹配的action才能启动相应的Service。

            3.4 小结

            通过Messenger来实现Activity和Service的交互,稍微深入一点我们就可以知道,其实Messenger也是通过AIDL来实现的。对於前两种实现方式,Messenger方式总体上来讲也是比较容易理解的,这就和平时使用Handler和Thread通信一个道理。

            4. 自定义接口交互

            何谓自定义接口呢,其实就是我们自己通过接口的实现来达到Activity与Service交互的目的,我们通过在Activity和Service之间架设一座桥樑,从而达到数据交互的目的,而这种实现方式和AIDL非常类似(后文会说到)。实现效果如图4.1:

    图4.1

            4.1 实现原理

            自定义一个接口,该接口中有一个获取当前下载进度的空方法。Server端用一个类继承自Binder并实现该接口,覆写了其中获取当前下载进度的方法。Client端通过ServiceConnection获取到该类的对象,从而能够使用该获取当前下载进度的方法,最终实现实时交互。

            4.2 实现步骤

            4.2.1 新建一个Interface,并在其中创建一个用于获取当前下载进度的的空方法getCurrentLoad()。

    [java] view plaincopy
    1. package com.seven.servicetestdemo;  
    2.   
    3. public interface ICountService {  
    4.     public int getCurrentLoad();  
    5. }  

            4.2.2 新建Server端DownService实现ICountService并在其中通过一个内部类ServiceBinder继承自Binder并实现ICoutService接口。

    [java] view plaincopy
    1. public class DownLoadService extends Service implements ICountService{  
    2. private ServiceBinder serviceBinder = new ServiceBinder();    
    3. public class ServiceBinder extends Binder implements ICountService{  
    4.     @Override  
    5.     public int getCurrentLoad() {  
    6.         Log.i(TAG, "ServiceBinder getCurrentLoad()... i=:"+i);  
    7.         return i;  
    8.     }     
    9. }  
    10. @Override  
    11. public int getCurrentLoad() {  
    12.     return 0;  
    13. }  
    14. }  
              在Server端中,实现获取下载进度的空方法getCurrentLoad();这是Eclipse自动生成的,重点不在这裡。我们需要在ServiceBinder类中覆写getCurrentLoad()方法,这裡我们返回当前的下载进度i。

           4.2.3 Client端使用bindService()绑定Server端。

    [java] view plaincopy
    1. if (startSerBtn == v) {  
    2.     Log.i(TAG, "Start Button Clicked.");  
    3.     bindService(intent, serConn, BIND_AUTO_CREATE);  
    4.     timer.schedule(new MyTimerTask(), 1000, TIME * 1000);//这里一定要延迟一下再开始获取数据,不然会报空指针异常  
    5. }  
               在Client端绑定Server端的同时,延迟1s开始获取下载进度。其中的intent = new Intent(“com.seven.test”)2com.seven.test该字符串要与在AndroidManifest.xml中申明的一致。

           4.2.4 Server端返回binder对象。

    [java] view plaincopy
    1. @Override  
    2. public IBinder onBind(Intent intent) {  
    3.     Log.i(TAG, "DownLoadService.onBind()...");  
    4.     return serviceBinder;  
    5. }  
               这里的serviceBinder因为继承了Binder因此也是Binder对象。

            4.2.5 Client端通过ServiceConnection来获取Server端的binder对象。

    [java] view plaincopy
    1. private ServiceConnection serConn = new ServiceConnection() {  
    2. @Override  
    3.     public void onServiceDisconnected(ComponentName name) {  
    4.         iCountService = null;  
    5.     }         
    6.     @Override  
    7.     public void onServiceConnected(ComponentName name, IBinder service) {  
    8.         Log.i(TAG, "onServiceConnected()...");  
    9.         iCountService = (ICountService)service;  
    10.     }  
    11. };  
              获取的过程是在bindService()过程中完成的,这里的iCountService是接口ICountService的对象,在这里得到实例化。

            4.2.6 在绑定完成之后,Server端会开启下载,在实际情况中Server端会开启独立线程用于下载,这里用i++来代替。

    [java] view plaincopy
    1. @Override  
    2. public void onCreate() {  
    3.     super.onCreate();  
    4.     Log.i(TAG, "DownLoadService.onCreate()...");  
    5.     timer = new Timer();  
    6.     timer.schedule(new MyTimerTask(), 0, TIME*1000);  
    7. }  
    8. class MyTimerTask extends TimerTask{  
    9.     @Override  
    10.     public void run() {  
    11.         if(100==i){  
    12.             i=0;  
    13.         }  
    14.         i++;  
    15.     }  
    16. }  
              bindService()方法执行之后会调用DownLoadService中的onCreate()方法,在其onCreate()方法中开启timer使得i++。

            4.2.7 Server端已经开启了下载,那么Client端需要及时获取下载进度并在主界面上更新。

    [java] view plaincopy
    1. Handler mHandler = new Handler(){  
    2.     @Override  
    3.     public void handleMessage(Message msg) {  
    4.         super.handleMessage(msg);  
    5.         Log.i(TAG, "handleMessage...");  
    6.         int curLoad = iCountService.getCurrentLoad();  
    7.         mProgressBar.setProgress(curLoad);  
    8.         currentTv.setText(curLoad+"%");  
    9.     }  
    10.  };  
    11. class MyTimerTask extends TimerTask{  
    12.     @Override  
    13.     public void run() {  
    14.         mHandler.sendMessage(mHandler.obtainMessage());  
    15.     }  
    16. }  
               Client端的Timer在bindService()完成之后1秒再开始获取下载进度,获取方法是直接通过int curLoad = iCountService.getCurrentLoad();这里的getCurrentLoad()方法是DownLoadService内部类ServiceBinder中的方法。Client端将获取到的下载进度更新到介面上并更新进度条。

            4.3 小结

            通过上面的例子可以知道,这种方法简单实用,扩展性强,但其也有一些缺点,比如需要延迟一些再开始获取Server端的数据,从而无法完全实现从零开始同步更新。综其所述,通过自定义接口实现Activity与Service交互的方法还是比较实用的。适用於同进程中通信,不能进行跨进程通信。

            5. AIDL交互

            什么是AIDL?

            AIDL是Android Interface Definition Language的首字母缩写, 也就是Android接口定义语言。提及AIDL就不得不说下Android的服务,Android 支持两种服务类型的服务即本地服务和远程服务。

            本地服务无法供在设备上运行的其他应用程序访问,也就是说只能该应用程序内部调用,比如某些应用程序中的下载类服务,这些服务只能由内部调用。而对于远程服务,除了可以由本应用程序调用,还可以允许其他应用程序访问。远程服务一般通过AIDL来实现,可以进行进程间通信,这种服务也就是远程服务。

            本地服务与远程服务还是有一些重要的区别。具体来讲,如果服务完全只供同一进程中的组件使用(运行后台任务),客户端一边通过调用 Context.startService()来启动该服务。这种类型的服务为本地服务,它的一般用途是后台执行长耗时操作。而远程服务一般通过bindService()方法启动,主要为不同进程间通信。我们也将远程服务称为AIDL支持服务,因为客户端使用 AIDL 与服务通信。Android中对于远程服务有多种叫法:远程服务、AIDL服务、外部服务和RPC服务。

            5.1 AIDL实现流程图

    图5.1

            这属于代理/存根结构,通过这张AIDL的流程图,很容易发现Android实现IPC其实是在原来的C/S框架上加入了代理/存根结构。

            比如,你到自动取款机上去取款。那么你就是客户(Client),取款机就是你的代理(Proxy);你不会在乎钱具体放在那里,你只想将你的钱从取款机中取出来。你同银行之间的操作完全是取款机代理实现。你的取款请求通过取款机传到另一边,即银行的服务器(Server)。它也没有必要知道你在哪儿取钱,它所关心的是你的身份和你取款多少。当它确认你的权限,就进行相应的操作,返回操作结果给取款机,取款机根据服务器返回结果,从保险柜里取出相应数量的钱给你。你取出卡后,操作完成。取款机不是直接同服务器连接的,他们之间还有一个“存根(Stub)”,取款机与存根通信,服务器与存根通信,从某种意义上说存根就是服务器的代理。实现效果如图5.2:

    图5.2

            5.3 实现原理

            AIDL属于Android的IPC机制,常用于跨进程通信,主要实现原理基于底层Binder机制。

            5.4 实现步骤

            5.4.1 建立工程。按照图5.3和图5.4建立AIDLServer端以及AIDLClient端。在AIDLServer端中只有一个服务程序,没有主界面,其主要功能就是负责下载。AIDLClient端从AIDLServer端获取当前下载进度(注:AIDLServer端和AIDLClient端是不同的两个APK,在模拟本例的时候,需要先在模拟器上安装AIDLServer编译出来的APK,安装方法可以直接在模拟器上运行一次,可以通过adb install your.apk 来安装)。

    图5.3

            AIDLServer端中新建了一个ICountService.aidl的文件,该文件内容如下:

    [plain] view plaincopy
    1. package com.seven.aidlserver;  
    2.   
    3. interface ICountService{  
    4.     int getCount();  
    5. }  

              aidl文件的书写规范如下:

            (1). Android支持String和CharSequence(以及Java的基本数据类型);

            (2). 如果需要在aidl中使用其它aidl接口类型,需要import,即使是在相同包结构下;

            (3). Android允许传递实现Parcelable接口的类,需要import;

            (4). Android支持集合接口类型List和Map,但是有一些限制,元素必须是基本型或者前面三种情况,不需要import集合接口类,但是需要对元素涉及到的类型import;

            (5). 非基本数据类型,也不是String和CharSequence类型的,需要有方向指示,包括in、out和inout,in表示由客户端设置,out表示由服务端设置,inout是两者均可设置。

    图5.4

             AIDLClient端需要将AIDLServer端的ICountService.aidl文件复製过去,这裡为了方便,新建了一个和Server端同名的包,并将ICountService.aidl放与其中。

             5.4.2 我们在Server端建立好ICoutService.aidl文件之后,Eclipse会在/gen/com.seven.aidlserver/目录下自动生成ICountService.java文件。该文件由Eclipse自动生成,请勿随便修改,后文我们需引用到的内容如下:

    [java] view plaincopy
    1. public static com.seven.aidlserver.ICountService asInterface(android.os.IBinder obj) {  
    2.     if ((obj == null)) {  
    3.         return null;  
    4.     }  
    5. android.os.IInterface iin = (android.os.IInterface) obj.queryLocalInterface(DESCRIPTOR);  
    6.     if (((iin != null) && (iin instanceof com.seven.aidlserver.ICountService))) {  
    7.         return ((com.seven.aidlserver.ICountService) iin);  
    8.     }  
    9.     return new com.seven.aidlserver.ICountService.Stub.Proxy(obj);  
    10. }  

              5.4.3 在Server端新建一个内部类继承自ICountService.Stub并覆写其中的getCount()方法,以及实例化该类的一个对象serviceBinder。

    [java] view plaincopy
    1. private AIDLServerBinder serviceBinder = new AIDLServerBinder();  
    2. class AIDLServerBinder extends ICountService.Stub{  
    3.     @Override  
    4.     public int getCount() throws RemoteException {  
    5.         return i;  
    6.     }  
    7. }  
             这里与前面提到的“通过接口实现交互”非常类似。

            5.4.4 在Server端的onBind()方法中,返回前面的serviceBinder对象。

    [java] view plaincopy
    1. @Override  
    2. public IBinder onBind(Intent intent) {  
    3.     Log.i(TAG, "AIDLServer.onBind()...");  
    4.     return serviceBinder;  
    5. }  

             5.4.5 在Server端的onCreate()方法中,开启timer,模拟下载。在Client端通过bindService()绑定Server端的时候,会首先执行Server端的onCreate()方法。


    [java] view plaincopy
    1. @Override  
    2. public void onCreate() {  
    3.     super.onCreate();  
    4.     Log.i(TAG, "AIDLServer.onCreate()...");  
    5.     mTimer = new Timer();  
    6.     mTimer.schedule(new MyTimerTask(), 0,TIME * 1000);  
    7. }  
    8. class MyTimerTask extends TimerTask{  
    9.     @Override  
    10.     public void run() {  
    11.         if(i==100){  
    12.             i=0;  
    13.         }  
    14.         i++;  
    15.     }  
    16. }  

              5.4.6 Client端通过bindService()绑定Server端。


    [java] view plaincopy
    1. if(startBtn==v){  
    2.     Log.i(TAG, "start button click.");  
    3.     mIsBind = bindService(intent, serConn, BIND_AUTO_CREATE);  
    4.     mTimer.schedule(new MyTimerTask(), 1000 ,TIME * 1000);  
    5. }  
              这里的intent = new Intent(“com.seven.aidlserver”);这里跟Server端注册Service时过滤的要一致,也就是说只有发出相同的action才会启动该Service。同时开启了一个timer用于获取下载进度。
            5.4.7 Client端通过ServiceConnection来获取Server端的binder对象。

    [java] view plaincopy
    1. private ServiceConnection serConn = new ServiceConnection() {         
    2.     @Override  
    3.     public void onServiceDisconnected(ComponentName name) {  
    4.         iCountService = null;  
    5.     }         
    6.     @Override  
    7.     public void onServiceConnected(ComponentName name, IBinder service) {  
    8.         Log.i(TAG, "AIDLClient.onServiceConnected()...");  
    9.         iCountService = ICountService.Stub.asInterface(service);  
    10.     }  
    11. };  
              这里的iCountService对象实际上就是ICountService的对象在此实例化。

            5.4.8 获取当前下载进度并更新到界面上。

    [java] view plaincopy
    1. Handler mHandler = new Handler(){  
    2.     @Override  
    3.     public void handleMessage(Message msg) {  
    4.         super.handleMessage(msg);  
    5.         try {  
    6.             int count =  iCountService.getCount();  
    7.             mTextView.setText(count+"%");  
    8.             mProgressBar.setProgress(count);  
    9.         } catch (RemoteException e) {  
    10.             e.printStackTrace();  
    11.         }  
    12.     }  
    13. };  
              通过更新介面上的进度条,可以狠容易的后去当前下载进度。因為AIDLServer端只是一个继承自Service的服务,因此就不贴出其AndroidManifest.xml文件了。

            5.5 小结

            AIDL在Android中是进程间通信常用的方式,可能使用较為复杂,但效率高,扩展性好。同时很多系统服务就是以这种方式完成与应用程序通信的。

            本文通过五个例子,分别介绍了五种与Service交互的方法,这些方法有的简单,有的可能要复杂一些。在这里只是做为对Servie的一些总结。后文附上源码下载链接,不需要积分的哦。:D

            源码下载

            所有源码均在Ubuntu 10.04 Eclipse-Indigo下实验通过 模拟器采用的是2.3的镜像

    展开全文
  • 11优秀的交互设计作品集

    万次阅读 2019-10-13 16:40:30
    本文转自墨刀编译自Vanschneider的10 inspiring ...虽然很多交互设计师可能认为自己的工作不能很好地视觉化的方式呈现出来,但一作品集对于交互设计工作来说真的很重要。 在交互设计作品集中,可以引导人们了解...

    本文转自墨刀编译自Vanschneider的10 inspiring ux portfolios and why they work。

    不管你做什么样的设计,一个在线交互设计作品集都是必备的。在大多数情况下,公司和客户根本不会考虑你是做什么工作的。虽然很多交互设计师可能认为自己的工作不能很好地以视觉化的方式呈现出来,但一个作品集对于交互设计工作来说真的很重要。

    在交互设计作品集中,可以引导人们了解你的工作流程,分享你在简历甚至谈话都无法完全阐述出的细节。一个交互设计作品集将帮助面试官和用户都能更好地理解你的想法,以及你与众不同的地方。

    通过与Semplice(我的设计师作品集系统)的合作,我看到了很多例子,这些例子表明:即使是复杂的交互设计工作也可以漂亮的作品集的方式呈现出来。 我们可以去留意一些有才华的UI设计师的作品集,学习用可视化的方式来展现你的作品集,进而让人们对此留下深刻的印象。

    1. Kurt Winter

    在这里插入图片描述

    我最喜欢Kurt 的交互设计作品集的一点是:它看起来最不像是一个作品集。对于交互设计作品集来说,很容易塞满一些原型图,堆砌文字。 Kurt 确实分享了所有必要的细节,但同时成功地使它具有视觉吸引力。注意观察一下他的布局、图标和文本,这些都是值得学习借鉴的。

    在这里插入图片描述

    点击访问Kurt Winter的作品集

    2. Liz Wells

    在这里插入图片描述

    Liz Wells 是我们交互设计作品集的代言人。 她的作品集不仅让人眼前一亮,而且让人很容易理解她到底在做什么,以及她的作品是如何融入一个成功的最终产品的。每个案例研究都讲述一个具有相似结构的故事:

    • 项目摘要

    • 目前的任务

    • 用户体验的挑战

    • UX解决方案

    这使得读着很容易理解她从头到尾的方法流程。最令人印象深刻的是,她用了大量的图片来说明她的创作过程: 早期的草图,批注笔记,线框图。 许多这样的视觉效果都是简单地从笔记本上撕下来的,或者快速地写在白板上——这些视觉效果是任何UX设计师在随时随刻都能得到的。但 Liz 做的还远远不止这些,她拍摄这些笔记就像你拍摄印刷品一样,有互补的背景和可爱的小道具。她将最终产品的图片和视频呈现出来,让这个项目在屏幕上栩栩如生。

    在这里插入图片描述

    你可能会认为没有太多要展示的过程,尤其是策略和研究阶段,但是即使是头脑风暴的速记笔记也可能对你的交互设计作品集有价值。 将这些小片段保存在你的整个项目中,你会惊奇地发现这个故事在之后是多么的容易拼凑起来。

    点击访问Liz Wells的作品集

    3. Isa Pinheiro

    在这里插入图片描述

    与Liz的“幕后“式的案例研究相反,Isa Pinheiro在她的交互设计作品集中分享了精美的成品,并解释了她的工作如何影响最终用户。

    以她在日本铁路系统的项目为例。Isa在页面中嵌入了交互式原型,因此读者可以直接从她的产品作品集中体验成品。如果你没有从早期项目阶段分享的点点滴滴,这是一个很好的解决方案。

    在这里插入图片描述
    在这里插入图片描述

    (用墨刀做的交互原型,可以获取分享链接分享到作品集里)

    艾萨(Isa)还花时间在自己的作品集中添加了一些个人风格。看看她的两个独特的导航选项:一个是带有两个直接菜单项的全屏导航,另一个是每个项都配图的图像式导航。平滑的滚动和全屏封面滑块为她的交互设计作品集增添了视觉冲击。

    点击访问Isa的作品集

    4. Oykun Yilmaz

    在这里插入图片描述

    Oykun Yilmaz 擅长用一句话介绍客户并简要概述项目目标,从而使他的项目摘要简短而优美。 但是他会确保用精准的数字来呈现具体的结果,这往往是许多交互设计作品集案例研究都缺乏的。交互工作在人们看来似乎是抽象的,所以可以通过解释你的工作是如何产生实际影响的,让它具体化。

    点击访问Oykun Yilmaz的作品集

    5. Naim Sheriff

    在这里插入图片描述

    Naim Sheriff的主题对于读者来说看起来很简洁,使读者看起来很真实。 以他的Ideapaint案例研究为例,他在其中分享“设计探索”阶段的重要性,以及他通常如何进行。 甚至例出了在项目过程中问自己的问题,例如:“我们如何成功展示出相似产品之间的差异?用户怎么知道该为其的空间买多少油漆?” 随后,他们团队分享了解决方案。

    对于那些可能需要交互设计师,但又不了解内部术语和工作方式的客户来说,这样的交互设计作品集更加接地气。这样的作品集能让任何人,即使是招聘员(可能对设计一无所知)都容易理解你所做的工作。

    在这里插入图片描述

    点击访问Naim Sheriff作品集

    6. Sebastián Martínez

    在这里插入图片描述

    SebastiánMartínez 用单页作品集的方式带你了解他的作品。 他的案例研究很短,但是他做了很多设计师忘记做的一件事:他分享了他对最终产品的感觉。 “这是我感到自豪的最完整,最有趣的产品之一,”SebastiánMartínez谈到他的 Monkop Test Cloud 项目时说道。分享对工作的感受不会花费你的太多时间,但很有价值。

    在我们的“如何在X找到工作”系列中,我采访了顶级公司的设计师和招聘人员,只是询问我们如何能够在他们的设计团队中获得一份理想的工作。 他们中的许多人都说,他们想知道你对项目和结果的看法。 它给你的工作带来了深度,并给了我们一个进入你心灵的窗口。

    点击访问Sebastián Martínez的作品集

    7. Husam Elfaki

    在这里插入图片描述

    Husam Elfaki的交互设计作品集案例研究在第一段会介绍项目、目标和结果。但他并没有就此打住,把一堆照片扔在下面,而是将项目分解,解释项目的每一部分。

    不要想着放上图片你的读者能够理解它们的意思——花时间去写上标题或简短的摘要,解释你项目的来龙去脉。

    点击访问Husam Elfaki的作品集

    8. Kali and Karina

    在这里插入图片描述

    从概念到成品,Kali and Karina 的工作涉及到全流程。她们很少提到UX/UI这些字眼,但这都隐含在他们的案例研究中。从精心设计的用户旅程、黑白草图到高保真的原型图,她们像讲故事一样分享她们的项目。

    点击访问Kali and Karina 的作品集

    在这里插入图片描述

    (通过墨刀制作的高保真交互原型)

    9. Elliot Owen

    在这里插入图片描述

    Elliot Owen 呼吁人们注意特定的手势、互动和经验,这使他的项目取得成功。以他的 British Airways 为例。

    在这里插入图片描述

    他展示了小的功能或特性如何对项目产生重大影响。 而且他在合适的地方使用的GIF,不是为了让观众眼花缭乱或分心,而是准确地展示了他的交互设计项目的工作方式。

    点击访问Elliot Owen的作品集

    10. Veda Dsiljak

    在这里插入图片描述

    Veda Dsiljak的案例研究几乎就像是产品营销页面,他们的作品销售得如此出色。不只是用产品或项目的标题来命名页面,而是为它们撰写一个性标题。它们的作用就是一开始就引起人们的兴趣。 他在每个案例的结尾都添加了原型的下载链接,以便读者可以亲自体验。

    点击访问Veda Dsiljak的作品集

    11. Jason Yuan

    在这里插入图片描述

    我们以上分享的一些示例是允许你在作品集上直接跟原型进行交互,但 Jason Yuan 是使用带有鼠标操作轨迹的视频来可视化体验。通过这种方式,他能引导读者无障碍地明白产品的使用过程。

    年轻设计师们可以学习这一点:Jason为Apple设计的作品是自发的重新设计,但设计是如此详尽周到,感觉就像是真正的客户作品。 自发的重新设计是一种很好的方式,可以在你的职业生涯初期或你希望进入新的设计道路时展示你的技能和兴趣。 我总是建议说不要给像苹果这样的大公司进行自发设计,因为它们已经是一个成熟的知名品牌,这太容易了。 不过对于Jason来说,他成功做到了对FastCoDesign,Next Web,Mic等产品的设计。

    点击访问Jason Yuan 的作品集

    在创建交互设计作品集时,就像在日常工作中一样,需要深思熟虑以及具有战略性。 花一些时间来解释你的流程,让你的读者了解你工作的每一个步骤,并说明它是如何产生影响的,这样你的交互设计作品集就能被记住了。

    ————————————

    展开全文
  • 前后端数据交互方式与过程

    千次阅读 2018-08-25 09:10:22
    前后端交互方式: 1.利用cookie对象  Cookie是服务器保存在客户端中的一小段数据信息。使用Cookie有一前提,就是客户端浏览器允许使用Cookie并对此做出相应的设置。一般不赞成使用Cookie。 (1)后台代码 ...

    前后端交互的方式:

    1.利用cookie对象 

    Cookie是服务器保存在客户端中的一小段数据信息。使用Cookie有一个前提,就是客户端浏览器允许使用Cookie并对此做出相应的设置。一般不赞成使用Cookie。

    (1)后台代码

    1. Cookie cookie=new Cookie("name", "hello");  
    2. response.addCookie(cookie);  

     

    (2)前台代码

    1. Cookie[] cookies=request.getCookies();  
    2. for(int i=0;i<cookies.length;i++){  
    3.         if(cookies[i].getName().toString().equals("name")){  
    4.             out.print(cookies[i].getValue());  
    5.         }  
    6. }  


     

     

    2.利用session对象

    session对象表示特定会话session的用户数据。客户第一次访问支持session的JSP网页,服务器会创建一个session对象记录客户的信息。当客户访问同一网站的不同网页时,仍处于同一个session中。

     

    (1)后台代码

    1. request.getSession().setAttribute("name", name);  
    2. request.getSession().setMaxInactiveInterval(2);  
    3. response.sendRedirect("welcome.jsp");  

     

    (2)前台代码(jsp页面)

    Object user=request.getSession().getAttribute("name");

    3.利用request重定向,设置setAttribute

     

    (1)后台代码

    1. request.setAttribute("name", "cute");  
    2. request.getRequestDispatcher("welcome.jsp").forward(request, response);  //网址不会改变  

     

    PS:如果后台使用的转发代码为 response.sendRedirect("welcome.jsp");  //网址变为welcome.jsp

    则request设置的参数无效,因为已经切换到另一个请求了,request参数的有效期为本次请求。

    (2)前台代码

    String name=request.getAttribute("name").toString();  

     

     

    4.利用Ajax进行异步数据请求(得到的数据可以以json或xml格式返回,便于处理)

    (1)后台代码案例(运用servlet传输数据)

    public class TestServlet extends HttpServlet {  
      
        /** 
         * Constructor of the object. 
         */  
        public TestServlet() {  
            super();  
        }  
      
        public void doGet(HttpServletRequest request, HttpServletResponse response)  
                throws ServletException, IOException {  
            doPost(request, response);  
        }  
      
        public void doPost(HttpServletRequest request, HttpServletResponse response)  
                throws ServletException, IOException {  
      
            response.setContentType("text/html");  
            PrintWriter out = response.getWriter();  
            String data="[{\"name\":\"apple\",\"price\":23},{\"name\":\"banana\",\"price\":12},{\"name\":\"orange\",\"price\":8}]";  
            out.write(data);  
            out.flush();  
            out.close();  
        }  
      
        /** 
         * Initialization of the servlet. <br> 
         * 
         * @throws ServletException if an error occurs 
         */  
        public void init() throws ServletException {  
            // Put your code here  
        }  
      
    }  


    2.前台js请求处理数据代码

        function createXMLHttpRequest(){  
            var xmlrequest;  
            if(window.XMLHttpRequest){  
                xmlrequest=new XMLHttpRequest();  
            }else if(window.ActiveXObject){  
                try{  
                    xmlrequest=new ActiveXObject("Msxm12.XMLHTTP");  
                }catch(e){  
                    try{  
                        xmlrequest=new ActiveXObject("Microsoft.XMLHTTP");  
                    }catch(e){  
                        xmlrequest="";  
                    }  
                }  
            }  
            return xmlrequest;  
        }  
        //获取数据的函数  
        function change(){  
            var xmlrequest=createXMLHttpRequest();  
            xmlrequest.open("POST","TestServlet",true);  
            xmlrequest.onreadystatechange=function(){  
                if(xmlrequest.readyState==4&&xmlrequest.status==200){  
                    var data=JSON.parse(xmlrequest.responseText);  
                    var content="<table border=1>";  
                    for(var i=0;i<data.length;i++){  
                        content+="<tr>";  
                        for(o in data[i]){  
                            content+="<td>"+data[i][o]+"</td>";  
                        }  
                        content+="</tr>";  
                    }  
                    content+="</table>";  
                    document.getElementById("test").innerHTML=content;  
                }  
            };  
            xmlrequest.send();  
        }  
    
    

     

    总结:在用户访问网站整个生命周期中都会用到的数据用session来存储,例如用户名,登录状态,购物车信息

               显示在网页上的信息数据大多通过 request或Ajax方式获取

     

    交互实现原理:

    1.前端请求数据URL由谁来写?
    
    在开发中,URL主要是由后台来写的,写好了给前端开发者.如果后台在查询数据,需要借助查询条件才能查询到前端需要的数据时,这时后台会要求前端提供相关的查询参数,这里的查询参数也就是URL请求的参数。
    
    
    2.接口文档主要由谁来写?
    
    接口文档也是主要由后台开发者来写的,因为直接跟数据打交道的就是后台,后台是最清楚,数据库里面有什么数据,能返回什么数据.前端开发只是数据的被动接受者.所以接口文档也主要是由后台来完成的,前端只是接口文档的使用者,使用过程中,发现返回的数据不对,则需要跟后台进行商量,由后台来修改.切记 前端不要随意更改接口文档,除非在取得后台开发人员的同意的情况下.总的来讲,接口文档主要由后台来设计,修改,前端开发者起到了辅助的作用。
    
    
    3.前端开发与后台交互的数据格式主要是什么?
    
    主要是JSON
    XML现在用的不多
    
    
    4.前端开发的后台交互原理?
    
    在项目的时候,我们前后端会大概说一下接口地址,前端请求的参数,后端返回的参数,然后大家就开始写,写的差不多的时候,大家调一下接口看一下返回的数据,没问题就可以了。
    
    
    5.前端请求参数的形式
    
    GET和POST两种方式
    对安全性不高 采用get方便
    post要比get安全
    GET - 从指定的服务器中获取数据
    POST - 提交数据给指定的服务器处理
    
    
    6.前端应该告知后台哪些有效信息,后台才能返回前端想的数据的呢?
    
    先将要展示的页面内容进行模块划分,将模块的内容提取出来,以及方便前端的一些标志值等,将所有想要的内容和逻辑告知后端,
    后端就会去数据库里面去查找相应的数据表中去获得相应的内容,或者图片地址信息。
    URL中的参数主要是根据后台需要,如果后台需要一个参数作为查询的辅助条件 前端在URL数据请求时就传递参数。
    参数前面?
    几个参数中间&
    
    
    7.我们应该怎么把页面这些信息有效传达给后台,以及后台是如何获取到这些数据?
    
    总的来讲:所有前端请求的URL后面的参数,都是辅助后台数据查询的.如果不需要参数,那么后台就会直接给个URL给前端。
    
    
    8.前端应该如何回拒一些本不属于自己做的一些功能需求或任务?
    
    在与后台打交道中,我们经常遇到这种情况,有时候明明后台来处理某个事件很简单,后台非要你来做,这时候我们应该懂得去回绝他。
    原则:前端就是负责把数据展示在页面上
    发挥:这就需要我们对一个需求,一个任务的要有清晰认识了,如果对任务含糊不清,自己都没搞明白,你只能受后台摆布了.最后也会因为任务没有完成而备受责难了。
    
    
    9.当前端在调用数据接口时,发现有些数据不是我们想要的,那么前端应该怎么办呢或者怎么跟后台讲呢?
    
    首先要把请求的URL和返回的数据以及在页面的展示的情况给跟后台看,这样有理有据,后台开发人员是不会说什么的,否则,后台会很不耐烦的,甚至骂你的可能都有,本身做后台比较难,尤其在查询数据,取数据,封装数据方面都比较难处理。
    
    
    10.为什么需要在请求的时候传入参数?
    
    因为后台在查询数据库的时候需要条件查询。
    展开全文
  • 本文信息来源于网络,本人只是汇总。VS创建项目,项目类型选择Window服务为服务创建安装程序1.. 返回到 Service1 的“设计”... 默认情况下,向您的项目添加包含两安装程序的组件类。将该组件命名为 ProjectInstall

    本文信息来源于网络,本人只是汇总。

    VS创建项目,项目类型选择Window服务

    为服务创建安装程序

    1.. 返回到 Service1 的“设计”视图。
    2.. 单击设计器的背景以选择服务本身,而不是它的任何内容。
    3.. 在“属性”窗口中,单击属性列表下面灰色区域中的“添加安装程序”链接。
    默认情况下,向您的项目添加包含两个安装程序的组件类。将该组件命名为
    ProjectInstaller,它包含的安装程序分别是服务的安装程序和服务关联进程的安装程
    序。

    4.. 访问 ProjectInstaller 的“设计”视图,然后单击“ServiceInstaller1”。
    5.. 在“属性”窗口中,将 ServiceName 属性设置为 MyNewService。
    6.. 将 StartType 属性设置为 Automatic。
    7.. 在设计器中,选择 ServiceProcessInstaller1(针对 Visual Basic 项目),
    或 serviceProcessInstaller1(针对 Visual C# 项目)。将 Account 属性设置为
    LocalService。这将使得在本地服务帐户上安装和运行该服务。有关更多信息,请参见
    ServiceProcessInstaller.Account 属性。
    安全说明 LocalService 帐户用作本地计算机上的非特权用户,向任何远程服务
    器显示匿名凭据。使用其他帐户时需要特别小心,因此它们具有较高的特权,会增加您
    受到恶意代码攻击的风险。

    设置服务为“允许服务与桌面交互”
    如需设置“允许服务与桌面交互“上文中的第7步:Account的属性必须设置为LocalSystem,然后在ProjectInstaller.cs中ProjectInstaller类中重载OnAfterInstall,如下代码:

    [RunInstaller(true)]
        public partial class ProjectInstaller : System.Configuration.Install.Installer
        {
            public ProjectInstaller()
            {
                InitializeComponent();
            }
    
            protected override void OnAfterInstall(IDictionary savedState)
            {
                try
                {
                    base.OnAfterInstall(savedState);
                    System.Management.ManagementObject myService = new System.Management.ManagementObject(
                        string.Format("Win32_Service.Name='{0}'", this.serviceInstaller1.ServiceName));
                    System.Management.ManagementBaseObject changeMethod = myService.GetMethodParameters("Change");
                    changeMethod["DesktopInteract"] = true;
                    System.Management.ManagementBaseObject OutParam = myService.InvokeMethod("Change", changeMethod, null);
                }
                catch (Exception)
                {
                }
            }
        }
    展开全文
  • 20.4 中介者模式总结 中介者模式将一网状的系统结构变成一个以中介者对象为中心的星形结构,在这星型结构中,使用中介者对象与其他对象的一对关系来取代原有对象之间的关系。中介者模式在事件驱动类...
  • 常见的Web实时消息交互方式和SignalR

    千次阅读 2017-05-16 15:08:11
    Web消息交互技术 1.1 常见技术 1.2 WebSocket介绍 1.3 WebSocket示例2. Signal 2.1 SignalR是什么 2.2 默认传输方式 2.3 指定传输方式 2.4 自动管理传输方式 2.5 通信模型 2.6 SignalR示例...
  • web前端后端数据的交互方式总结

    万次阅读 2016-05-04 01:41:29
    做web开发,很重要的一环节就是前后台的数据的交互,数据从页面提交到contoller层,数据从controler层传送到jsp页面来显示。这2过程中数据具体是如何来传送的,是本节讲解的内容。  首先说一下数据如何从后台...
  • 内核态与用户交互方式(1)

    千次阅读 2009-08-18 23:39:00
    引自http://www.ibm.com/developerworks/cn/linux/l-kerns-usrs/本人不具有任何版权,如转载...在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink 
  • 描述:在自己写的一系统服务程序,需要经常用到“允许与桌面进行交互”的设置,网上很使用修改注册表的形式实现,我测试过,修改注册表后,选中的勾是选上了,但不能弹出应用程序;据说重启电脑后可以,但我不想...
  • 前端与后端数据交互方式之ajax

    千次阅读 2019-10-02 23:33:36
    前端与后端数据交互方式之Ajax  对于前端学习而言,CSS+HTML+JavaScript的学习在自我学习的情况下掌握也不是很难,但是想要实现前后端的数据交互在没有指导的情况下学习会是一头雾水。接下来就让我来浅谈一下...
  • 进程间交互的几种方式

    千次阅读 2016-04-11 21:27:30
    # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有...# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共
  • QCustomPlot之用户交互

    千次阅读 2015-09-29 20:42:06
    User interactions用户交互 QCustomPlot提供多种内置的用户交互。它们大致可以分为 1)范围操作通过鼠标拖拽或者滚动鼠标齿轮 2)通过点击选择Plot实体。 3)用户点击到Plot实体上发出信号 Range Manipulation范围...
  • web前后台数据交互方式

    千次阅读 2016-05-08 22:33:43
    做web开发,很重要的一环节就是前后台的数据的交互,数据从页面提交到contoller层,数据从controler层传送到jsp页面来显示。这2过程中数据具体是如何来传送的,是本节讲解的内容。  首先说一下数据如何从...
  • 在VRSamples中,我们构建了一简单的,可拓展的轻度系统,让用户跟场景中的物体进行交互。其中包含了三主要的脚本文件:VREyeRaycaster,VRInput和VRInteractiveItem,下面将对这三重要的类进行简要的介绍。相关...
  • 哎呀呀,,又遇到问题了,,查资料的过程中,看到这东东,,哈哈,不错,,先收住先,, 客户机重装系统WIN2K PRO版;在工作组模式中一切正常,加入域后也提示欢迎加入域 ,可重启后输入域用户名和密码却提示...
  • web 前后台数据交互方式

    万次阅读 2012-05-25 15:41:23
    做web开发,很重要的一环节就是前后台的数据的交互,数据从页面提交到contoller层,数据从controler层传送到jsp页面来显示。这2过程中数据具体是如何来传送的,是本节讲解的内容。  首先说一下数据如何从后台...
  • 与虚拟机交互文件的3种方式

    千次阅读 2018-08-22 11:02:53
    大家好,我是公众号逻辑熊猫带你玩Python的小编LogicPanda,今天的主题是“与虚拟交互文件的3种方法”。 在我们的学习过程中很多人都选择了使用虚拟机安装Linux操作系统或者是其他目的安装虚拟系统。这样做有很...
  • 枯燥繁杂的数据会让用户感到烦闷纠结,而设计师的巧妙设计能化腐朽为神奇,让数据以用户易于理解的方式呈现出来。那么下面整理25创意的交互式图表设计案例,希望能给你带来灵感。enjoy!你可能感兴趣的交ppt背景...
  • 随着互联网产品的不断发展,越来越的人意识到了用户体验的重要性,越来越的公司成立了UED相关的部门,并且职位划分已相当细致。但是UED中职能的划分,却大部分仅对接界面的层面。事实上,一互联网产品从策略的...
  • 第11章 用户交互

    千次阅读 2012-05-18 20:15:14
    如果用户不能和图形界面进行交互,它存在的意义有何在那?然而,核心动画的API显示,没有直接的方法可以接收用户交互。 这一章我们焦距于怎么给应用程序增加交互点,尤其是核心动画。下面我们就看鼠标和键盘的...
  • 再看语音交互设计

    千次阅读 2019-08-20 22:02:00
    赋能是人工智能对人类最重要的事情,而智能语音(例如DuerOS)正在为人机交互方式赋能。声音一直是人与人沟通的核心,而今也成为了人机交互的核心——智能语音交互。早在2016年,google声称其搜素请求中有20%是...
  • 用户测试:请目标用户使用产品来完成任务,观察并记录用户使用产品的整个过程. 用户测试的定义:也被称为产品可用性测试,指特定的用户在特定的使用场景中,为了达到特定的目标而使用某产品时,所感受到的有效性、...
  • 描述:在自己写的一系统服务程序,需要经常用到“允许与桌面进行交互”的设置,网上很使用修改注册表的形式实现,我测试过,修改注册表后,选中的勾是选上了, 但不能弹出应用程序;据说重启电脑后可以,但我不...
  • UML交互

    千次阅读 2015-06-09 10:56:48
    交互图描述的是一组对象之间的交互过程,或者说,这里我们实际上要回答这样一问题:“方法调用过程在UML中怎样表示?” UML交互图 本文将通过一非常简单的交易系统来说明UML交互图。这系统包含六Java类...
  • 人机交互期末复习

    千次阅读 2020-11-09 14:12:57
    按照需要支持或扩充的用户活动,选择适当的方法和技术,优化用户和系统、环境或产品之间的交互。 什么是交互设计: 设计支持人们日常工作和生活的交互式产品 人类通信和交互空间的设计,寻求支持人类的方法 创新...
  • 人机交互初认知

    千次阅读 2018-02-26 11:28:18
    人机交互与计算机科学、人机工程学、多媒体技术和虚拟现实技术、心理学、认知科学和社会学以及人类学等诸多学科领域有密切的联系,其中,认知心理学与人机工程学是人机交互技术的理论基础,而媒...
  • 如何将 Office 应用程序配置为在交互用户帐户下运行     概要:我们不建议也不支持从无人参与的用户帐户自动运行 Microsoft Office 应用程序。 有关我们为什么不建议在这种情况下自动运行...
  • 操作系统win2kserver,注销用户,更换名字登录,提示信息:此系统的本地策略不允许您采用交互式登录,如何设为允许,谢谢 用域管理员身份从某台工作站上登录服务器后再进一步修改回来. “拒绝本地登录”设...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 406,031
精华内容 162,412
关键字:

允许多个用户以交互方式