【问题标题】:Android Activity Flow - From Base Superclass to Subclass to Baseclass againAndroid Activity Flow - 从基础超类到子类再到基类
【发布时间】:2014-03-13 18:11:12
【问题描述】:

作为 android 的 N00bie,我正在尝试构建一个简单的地图应用程序。我开始在同一个班级做所有事情,但由于明显的原因,很快就失控了。所以我想拆分类,将基类作为活动的主要流程,将子类作为“实用程序”类。

所以我实例化了一个子类对象,并在子类的 onCreate 中开始调用方法。但是这些方法永远不会运行。我究竟做错了什么?一旦我创建了子类对象,子类的 onCreate 就应该触发,不是吗?而且,在子类中而不是在整个其他类中这样做甚至是聪明的方式吗?

提前致谢!

基类:

package com.example.TestMap;

import android.app.Activity;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;

public class MyActivity extends Activity  {

    private GoogleMap mMap;

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        LocationClass locationClass = new LocationClass();



    }

    public void setMap(){
        Log.i("TestMap", "setMap");
        mMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
        mMap.setMyLocationEnabled(true);

    }



    public void setCamera(Location location) {

        Log.i("TestMap", "setCamera");

        final LatLng locationLatLng = new LatLng( (location.getLatitude() ), location.getLongitude() );


        CameraPosition cameraPosition = new CameraPosition.Builder()
                .target(locationLatLng)      // Sets the center of the map to Mountain View
                .zoom(17)                   // Sets the zoom
                .bearing(90)                // Sets the orientation of the camera to east
                .tilt(30)                   // Sets the tilt of the camera to 30 degrees
                .build();                   // Creates a CameraPosition from the builder

        mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
    }

}

子类

package com.example.TestMap;

import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import java.util.List;


public class LocationClass extends MyActivity implements LocationListener {

    private LocationManager locationManager;
    private String provider;
    private List<String> providers;


    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("TestMap", "LocationClass OnCreate");
        GetProivder();
    }


    public void GetProivder (){
        Log.i("TestMap", "LocationClass GetProivder");


        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        Criteria criteria = new Criteria();
        criteria.setAccuracy(2);
        provider = locationManager.getBestProvider(criteria, false);
        providers = locationManager.getProviders(true);

        Location location = locationManager.getLastKnownLocation(provider);

        Log.i("TestMap", "providerlist = " + providers);
        Log.i("TestMap", "getBestProvider = " + provider);
        Log.i("TestMap", "Location = " + location);

        if (location != null) {
            Log.i("TestMap", "Provider " + provider + " has been selected.");
            super.setCamera(location);
            super.setMap();

        } else {
            Log.i("TestMap", "location is null.");

        }
    }


    @Override
    public void onLocationChanged(Location location) {
        Log.i("TestMap", "onLocationChanged");
    }

    @Override
    protected void onResume() {
        super.onResume();
        locationManager.requestLocationUpdates(provider, 400, 1, this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        locationManager.removeUpdates(this);
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        Log.i("TestMap", "onStatusChanged");
    }

    @Override
    public void onProviderEnabled(String provider) {
        Toast.makeText(this, "Enabled new provider " + provider,
                Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onProviderDisabled(String provider) {
        Log.i("TestMap", "onProviderDisabled");
        Toast.makeText(this, "Disabled provider " + provider,
                Toast.LENGTH_SHORT).show();
    }


}

【问题讨论】:

    标签: java android android-activity subclass superclass


    【解决方案1】:

    你的代码

    LocationClass locationClass = new LocationClass(); 不会创建它。它只是将它作为一个对象,但它不绑定到生命周期并调用方法。

    您需要启动它以使其显示(并根据浏览您的代码获取整个屏幕)。当您这样做时,Android 会触发相应的方法调用。

    像这样:

    Intent intent = new Intent(this, LocationClass.class);          
    startActivity(intent);
    

    更多信息可以在这里找到:http://developer.android.com/training/basics/firstapp/starting-activity.html#StartActivity

    它也必须在你的清单中定义,否则它会崩溃。您的代码中还有其他明显的奇怪之处,您是否希望 LocationClass 扩展 MyActivity 而不是 Activity?您的 LocationClass 也不会在 onCreate 中调用 setContentView(),因此您不会看到 UI(据我所知),除非您希望通过 extends 部分看到它。

    编辑: 如果你扩展子类并将这个意图代码放在 onCreate 中,你可能会崩溃,因为它会在 MyActivity 中调用 super()(再次调用 onCreate(),因为它是超类),并且会不断做出更多意图来启动活动。如果这是“父”类,则不应将 MyActivity 子类化。

    您应该只继承 Activity 或全局父 Activity(例如,在我现在的项目中,我扩展 SpiceActivity,因为它们都使用与 Spice 相关的通用组件)。

    【讨论】:

    • 感谢您的快速回复。 “占据整个屏幕”是什么意思?要清楚;我希望子类包含向 locationlistener 描绘的所有内容,并定期向 MyActivity 发送位置,相机在收到新位置后会自行重置。所以 LocationClass 中没有发生 UI 的事情。它最初是一个子类,因为我也想使用 MyActiviy 中的一些字段,但回想起来,它现在并不需要。它只需要实例化并启动,然后定期发送一些数据。视图和 UI 应保留在 MyActivity 上。
    • 你应该使用类似的服务。 Activity 是基于 UI 的(主要)项目——Activity 具有操作栏、内容窗口和生命周期等。听起来您想要一个没有 UI 的服务。服务非常复杂...我实际上没有使用过,所以我无法就它们提供真正的建议。
    【解决方案2】:

    子类的onCreate 方法应在 Android 创建时调用(请参阅Understanding the Lifecycle Callbacks),例如,当向该 Activity 发出 Intent 时会发生这种情况。

    编辑:我刚刚看到@Mgamerz 的回答,并意识到您的超类 Activity 中的那一行是您试图让 Android 创建子类 Activity 的地方。下一段现在有些无关紧要,但请注意,您仍然需要将子类活动添加到清单文件中。

    您确定您的应用程序实际上正在启动子类 Activity,还是仍在启动超类 Activity?您可能需要查看项目的“AndroidManifest.xml”文件并检查是否存在与子类 Activity 对应的 &lt;activity /&gt; 元素。


    如果超类具有可以/将被多个子类活动重用的功能,我认为将类拆分为超类和子类是明智的。例如,您可能有像DirectionsActivitySearchActivity 这样的子类活动,它们的超类MapActivity 提供了一些常见的地图相关活动。即使您现在只有一个子类 Acitivty,如果您认为以后可能会编写其他与地图相关的活动,那么拥有一个超类和一个子类可能仍然有意义。我认为仅仅因为单个类变得太长而将类分成超类和子类是不明智的。如果你只是想要一个辅助类并且你不希望将来有更多的MapActivity 子类,你可以在与活动类相同的包中创建一个MapUtils 类,这将定义一些static 辅助类方法。例如,您可以将 GetProvider 方法放入这样的帮助程序类中。草图示例(注意 MapHelperpackage-private 访问):

    class MapHelper {
    
        static Location getProvider() {
            // ...
            return location;
        }
    
        // Other helper methods here
    }
    
    public class MyActivity extends Activity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            // ...
            setCamera(MapHelper.getProvider());
            setMap();
        }
    
        // Other activity methods here
    }
    

    【讨论】:

    • MyActivity 在应用启动时仍然运行。就像我对@Mgamerz 的回答所评论的那样,我基本上只需要一个在后台运行的子类来处理位置监听器。 Locationlistener 每次感知到变化时都会触发 onCreate,因此我还需要在该类中使用 OnCreate,并在完成后将更新的位置发送回 MyActivity。
    • 你可能需要一个这样的服务,你的每个活动都可以挂钩(然后在它们被破坏时丢失,否则你会发生内存泄漏)
    • 同意@Mgamerz 使用服务。
    猜你喜欢
    • 2011-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-07
    • 1970-01-01
    相关资源
    最近更新 更多