工作线程上的PubNub

时间:2016-05-24 23:09:44

标签: android multithreading google-maps pubnub

TL; DR见下文

我的Android应用程序的核心功能是在前台服务中广播用户的当前位置,该服务在从活动中解除绑定后继续运行。在发布到频道和从频道接收数据的订阅者方面,我的一切工作正常。服务很好。我甚至设置了谷歌地图相机的动画,以便按照订阅信息中的位置进行操作。

我担心的是,我收到了这条消息:

I/Choreographer: Skipped 49 frames!  The application may be doing too much work on its main thread.

我当然研究了这条消息。很多人似乎都说它与动画有关,所以我认为它与地图有关,因为它是唯一动画的东西。虽然,我也了解到编舞者可以因其他原因而产生这种信息。

当我的应用程序启动时,它会启动一个前台服务,该服务使用GoogleAPIClient连接到谷歌位置服务。初始化后,我立即请求我当前的位置并使用PubNub将lng和lat广播到一个频道。然后我订阅该频道,当收到消息时,我的MapFragmentPresenter类会侦听来自服务的位置更新。然后,演示者调用MapFragment的视图(MVP中的V)来为摄像机设置动画并将标记放置在每个新位置。

这一切都很好。我只是想确保我没有引起跳过的帧而不是在主线程上做太多工作。考虑到我计划在其上做的所有其他事情,我现在对主线程做的很少。现在我只是不断地重新定位相机以跟随设备的当前位置,我认为这是非常基本的。

另外,我没有使用任何唤醒锁功能,但我的PubNub广播工作正常。为什么是这样?我在某个地方看到,当设备被锁定时,使用PubNub运行需要这个,但我的工作没有它。

很抱歉这篇长篇文章。

注意:我没有大型资源文件。除了从AS本身导入的图标之外,我甚至还没有添加任何其他内容。

TL; DR 我似乎在主线程上做了太多。谷歌位置服务和PubNub操作可以在服务中的不同线程上完成,这将解决我的问题吗?

问题:

  1. 应该/我可以在工作线程上执行所有位置请求吗?
  2. 应该/可以将PubNub操作放在自己的线程上吗?
  3. 我做得不好吗?
  4. 当设备处于睡眠/锁定状态时,我的前台服务似乎工作得很好,但我根本没有弄乱WAKE_LOCK。我是不是该?当我的服务似乎正在做我期望的一切时,操纵锁定状态的区别是什么?
  5. 以下是一些代码:

    感谢您抽出宝贵时间!

    MapViewFragment

    public class MapViewFragment extends Fragment
            implements OnMapReadyCallback, IMapFragment {
    
        private static final String TAG = "MAP_VIEW_FRAGMENT";
    
        private MapView mapView;
        private GoogleMap gMap;
        private IMapPresenter presenter;
        private boolean mapReady;
        private Handler handler;
        private LatLng myLocation;
    
    
        //ToDo: newInstance method
    
        //==========================
        //Fragment Lifecycle
        //==========================
        @Override @Nullable
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                                 @Nullable Bundle savedInstanceState) {
    
            mapReady = false;
            presenter = new MapPresenter(this);
            View v = inflater.inflate(R.layout.map_view, container, false);
            handler = new Handler(Looper.getMainLooper());
    
            mapView = (MapView) v.findViewById(R.id.mapview);
            mapView.onCreate(savedInstanceState);
            mapView.getMapAsync(this);
    
            return  v;
        }
    
        @Override
        public void onResume() {
            super.onResume();
            mapView.onResume();
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            mapView.onDestroy();
        }
    
        @Override
        public void onLowMemory() {
            super.onLowMemory();
            mapView.onLowMemory();
        }
    
    
        public MapPresenter getPresenter(){
            return (MapPresenter) presenter;
        }
    
    
        //==========================
        //Map
        //==========================
        @Override
        public void onMapReady(GoogleMap googleMap) {
    
            this.gMap = googleMap;
            mapReady = true;
    
        }
    
    
        @Override
        public void moveToMyLocation(final LatLng locData) {
    
            handler.post(new Runnable() {
                @Override
                public void run() {
                    gMap.addMarker(new MarkerOptions().position(locData).title("myLocation"));
                    gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(locData,20));
                    Log.d(TAG,"//////////////////moveToMyLocation");
    
                }
            });
    
        }
    
    }
    

    服务

    public class MapService extends Service implements
            GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
            LocationListener {
    
        private static final String TAG = "MAP_VIEW_SERVICE";
    
        private int REQUEST_CODE = 101;
        private int NOTIFICATION_ID = 102;
    
        private LocationRequest gLocationRequest;
        private GoogleApiClient gApiClient;
    
        private Pubnub mPubnub;
    
        private Location lastLocation;
        private String mapFragTag;
    
        private final IBinder mBinder = new LocalBinder();
        private LatLng mLatLng;
    
        private ServiceRequestListener requestListener;
    
        //==========================
        //Service Lifecycle
        //==========================
        @Override
        public void onCreate() {
            super.onCreate();
    
            gLocationRequest = LocationRequest.create();
            gLocationRequest.setInterval(5000);
            gLocationRequest.setFastestInterval(5000);
            gLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    
            gApiClient = new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
    
            mPubnub = new Pubnub(
                    getString(R.string.pubnub_publish_key)
                    ,getString(R.string.pubnub_subscribe_key));
    
            try{
                mPubnub.subscribe("Channel-d2160eqlk",subscribeCallback);
            }catch (PubnubException e) {
                Log.e("**MapService**", e.toString());
            }
    
            gApiClient.connect();
            setupAndLaunchForeground();
    
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
                return START_STICKY;
    }
    
        @Nullable @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            if(gApiClient.isConnected()) {
                gApiClient.disconnect();
            }
        }
    
    
        public void setRequestListener(ServiceRequestListener requestListener) {
            this.requestListener = requestListener;
        }
    
    
        //==========================
        //StartForeground
        //==========================
        private void setupAndLaunchForeground() {
    
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
    
            builder.setSmallIcon(R.mipmap.ic_launcher)
                    .setContentTitle("Service Running")
                    .setTicker("AppName Services Initiated")
                    .setWhen(System.currentTimeMillis())
                    .setOngoing(true);
    
            Intent startIntent = new Intent(this, MapViewFragment.class);
    
            PendingIntent contentIntent = PendingIntent.getActivity(this,
                    REQUEST_CODE, startIntent, 0);
    
            builder.setContentIntent(contentIntent);
    
            Notification notification = builder.build();
    
            NotificationManager notificationManager =
                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    
            notificationManager.notify(NOTIFICATION_ID, notification);
    
            startForeground(NOTIFICATION_ID,notification);
    
        }
    
    
        //==========================
        //Google API Client
        //==========================
        @Override
        public void onConnected(@Nullable Bundle bundle) {
    
            PackageManager manager = getPackageManager();
            if(manager.checkPermission(Manifest.permission.ACCESS_FINE_LOCATION,"com.firsttread.appname")
                    == PackageManager.PERMISSION_GRANTED){
    
                LocationServices.FusedLocationApi.requestLocationUpdates(gApiClient, gLocationRequest, this);
                lastLocation = LocationServices.FusedLocationApi.getLastLocation(gApiClient);
            }
    
        }
    
        @Override
        public void onConnectionSuspended(int i) {
    
        }
    
        @Override
        public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    
        }
    
    
        //==========================
        //Location
        //==========================
        @Override
        public void onLocationChanged(Location location) {
    
            broadcastLocation(location);
            this.lastLocation = location;
    
            Log.d("****LocationChange****","Lat: " + location.getLatitude() + "Lng: " + location.getLongitude());
    
        }
    
    
        //==========================
        //PubNub
        //==========================
        private void broadcastLocation(Location location){
    
            JSONObject message = new JSONObject();
    
            try{
                message.put("lat", location.getLatitude());
                message.put("lng", location.getLongitude());
            }catch (JSONException e){
                Log.e("MapService", e.toString());
            }
    
            mPubnub.publish("ChannelName", message, publishCallback);
    
        }
    
        Callback publishCallback = new Callback() {
            @Override
            public void successCallback(String channel, Object response) {
                Log.d("**PUBNUB**", response.toString());
            }
    
            @Override
            public void errorCallback(String channel, PubnubError error) {
                Log.e("**PUBNUB**", error.toString());
            }
        };
    
        Callback subscribeCallback = new Callback() {
    
            @Override
            public void successCallback(String channel, Object message) {
    
                JSONObject jsonMessage = (JSONObject) message;
                try {
                    double mLat = jsonMessage.getDouble("lat");
                    double mLng = jsonMessage.getDouble("lng");
    
                    if(requestListener != null){
                        sendLocation(new LatLng(mLat,mLng));
                    }
    
    
                } catch (JSONException e) {
                    Log.e("**PUBNUB_ERROR**", e.toString());
                }
    
            }
        };
    
    
        //==========================
        //Location Data Methods
        //==========================
        private void sendLocation(LatLng locData){
            requestListener.retrieveLocation(locData);
        }
    
    
        //==========================
        //MapInterface
        //==========================
        public interface ServiceRequestListener {
            void retrieveAppNameLocations(HashMap<String,Long> memberLocations);
            void retrieveLocation(LatLng locData);
        }
    
        //==========================
        //ServiceBinder
        //==========================
        public class LocalBinder extends Binder {
            public MapService getService() {
                return MapService.this;
            }
        }
    
    
    }
    

1 个答案:

答案 0 :(得分:0)

您的问题的一些答案:

<强> 1。应该/我可以在工作线程上执行所有位置请求吗? 除了订阅将发布位置数据的频道之外,您不需要做任何特殊的事情。

<强> 2。应该/可以将PubNub操作放在他们自己的线程上吗? 他们将只使用异步API,而不是同步API(你不能在没有额外工作的情况下在Android中使用同步,否则Android会抛出异常)。

第3。我做得不好吗?当设备处于睡眠/锁定状态时,我的前台服务似乎工作得很好,但我根本没有弄乱WAKE_LOCK。我应该吗? 当你提出这个问题时,你可能已经配置了WAKE_LOCK,但可能不再允许在Android操作系统中使用(可能没有最终用户的额外权限),但这并不重要。只需在app处于后台时使用推送通知。

<强> 4。当我的服务似乎正在做我期望的一切时,操纵锁定状态的区别是什么? 不太确定你的意思,所以需要更多细节。

如果您仍然遇到上述问题,请submit full details to PubNub Support。发送样本项目压缩(如果可能),PubNub子键和PubNub SDK logs that captures any scenarios您遇到问题。