有关如何将位置连接代码从片段移动到MainActivity的提示?

时间:2017-12-03 17:26:56

标签: java android listview android-fragments

所以我有一个应用程序,它开始有4个独立的活动,但最近我决定最好有1个主要活动和4个碎片。

我现在的问题是,之前的两个活动(现在是片段)都包含位置连接代码,我需要将代码移动到我的MainActivity中,以便应用程序正确请求位置访问等,崩溃。

两个片段中的每个片段中的代码几乎相同,因此我只会在下面的示例中显示2个片段中的一个。

我对这个特定代码产生了一个主要问题:

private void handleNewLocation(Location location) {

        Log.i("TEST handleNewLocation", "Called handleNewLocation");
        // Returns the current adapter in use by the ListView supplied (mListView).
        LocationsAdapter adapter = (LocationsAdapter) mListView.getAdapter();
        adapter.setCurrentLocation(location);
        adapter.notifyDataSetChanged();
    }

正如您可能看到的那样,代码引用了ListView,该片段用于获取该ListView的正在使用的适配器:LocationsAdapter adapter = (LocationsAdapter) mListView.getAdapter();

我不知道如何将此代码移动到MainActivity中,仍然以某种方式从片段中引用ListView。要添加到该问题,我还需要在MainActivity中再次使用相同类型的代码,但也要在2的第二个片段中引用其他 ListView。

这是我的一个片段,也是它下面的MainActivity。

地点片段:

public class Locations extends Fragment implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener, LocationListener {

    public Locations() {
        // Required empty public constructor
    }

    private static final int PERMISSION_REQUEST_ACCESS_FINE_LOCATION = 100;

    private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;

    private static final String LOG_TAG = Locations.class.getName();

    private GoogleApiClient mGoogleApiClient;

    private LocationRequest mLocationRequest;

    Location mLocation = new Location(LocationManager.NETWORK_PROVIDER);

    private ListView mListView;

    public List<Word> locations = new ArrayList<>();

    // If the app already has the permission to access the user's location at high accuracy
    // (fine location), then connect to the GoogleApiClient.
    // If not, no connection-handling methods will be called.
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_ACCESS_FINE_LOCATION: {

                // Permission was granted, yay! Do the location-related task you need to do.
                if (ContextCompat.checkSelfPermission(getActivity(),
                        ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {

                    mGoogleApiClient.connect();
                }
            }
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.word_list, container, false);

        mListView = (ListView) rootView.findViewById(R.id.list);

        // The following code checks if the app has permission to access the user's fine location,
        // and requests the permission if necessary:
        if (ContextCompat.checkSelfPermission(getActivity(), ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
                    ACCESS_FINE_LOCATION)) {

                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.
                new MaterialStyledDialog.Builder(getActivity())
                        .setTitle(R.string.title_location_permission)
                        .setDescription(R.string.text_location_permission)
                        .setIcon(R.drawable.ic_place_white_48dp)
                        .withDialogAnimation(true)
                        .setPositiveText(android.R.string.ok)
                        .onPositive(new MaterialDialog.SingleButtonCallback() {
                            @Override
                            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                                //Prompt the user once explanation has been shown
                                ActivityCompat.requestPermissions(getActivity(),
                                        new String[]{ACCESS_FINE_LOCATION},
                                        PERMISSION_REQUEST_ACCESS_FINE_LOCATION);
                            }
                        })
                        .setNegativeText(android.R.string.no)
                        .show();

            } else {

                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(getActivity(), new String[]{ACCESS_FINE_LOCATION},
                        PERMISSION_REQUEST_ACCESS_FINE_LOCATION);

                // PERMISSION_REQUEST_ACCESS_FINE_LOCATION is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        }

        // Create the GoogleAPIClient object.
        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }

        // Create the LocationRequest object
        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(10 * 1000)        // 10 seconds, in milliseconds
                .setFastestInterval(1 * 1000); // 1 second, in milliseconds\


        locations.add(new Word("Bristol", R.drawable.bristol,
                41.674009, -71.279006));
        locations.add(new Word("Warren", R.drawable.warren_harbor,
                41.730647, -71.282688));
        locations.add(new Word("Newport", R.drawable.newport_breakers,
                41.486677, -71.315144));
        locations.add(new Word("Jamestown", R.drawable.jamestown,
                41.496313, -71.368435));
        locations.add(new Word("Beavertail Lighthouse", R.drawable.beavertail,
                41.458054, -71.395744));
        locations.add(new Word("Providence", R.drawable.providence,
                41.830279, -71.414955));
        locations.add(new Word("Roger Williams Park", R.drawable.roger_williams_park,
                41.785836, -71.418525));
        locations.add(new Word("Colt State Park", R.drawable.colt_state_park,
                41.682970, -71.297362));
        locations.add(new Word("Blithewold", R.drawable.blithewold,
                41.6540652,-71.2681633));
        locations.add(new Word("Narragansett", R.drawable.narragansett,
                41.433179,-71.457148));
        locations.add(new Word("Barrington", R.drawable.barrington_town_hall,
                41.740674, -71.308610));

        ViewCompat.setNestedScrollingEnabled(mListView, true);

        mListView.setAdapter(new LocationsAdapter(getActivity(), locations, mLocation));

        return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public void onStart() {
        // If the app already has the permission to access the user's location at high accuracy
        // (fine location), then connect to the GoogleApiClient.
        if (ContextCompat.checkSelfPermission(getActivity(),
                ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED || mGoogleApiClient != null) {
            mGoogleApiClient.connect();
        }
        super.onStart();
    }

    @Override
    public void onResume() {
        // If the app already has the permission to access the user's location at high accuracy
        // (fine location), then connect to the GoogleApiClient.
        if (ContextCompat.checkSelfPermission(getActivity(),
                ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            mGoogleApiClient.connect();
        }
        super.onResume();

        // Instantiate the locations ArrayList.
        locations = new ArrayList<>();
    }

    @Override
    public void onPause() {
        super.onPause();
        // If the user has paused the app and the GoogleApiClient is currently connected,
        // remove location updating, and disconnect from the GoogleApiClient.
        if (mGoogleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,
                    this);
            mGoogleApiClient.disconnect();

            locations.clear();
        }
    }

    public void onStop() {
        // If the user has stopped the app, disconnect from the GoogleApiClient.
        mGoogleApiClient.disconnect();
        super.onStop();
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.i(LOG_TAG, "Location services connected.");

        mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);

        if (mLocation == null) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
                    mLocationRequest, this);
        } else {
            handleNewLocation(mLocation);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.i(LOG_TAG, "Location services suspended. Please reconnect.");
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        if (connectionResult.hasResolution()) {
            try {
                // Start an Activity that tries to resolve the error
                connectionResult.startResolutionForResult(getActivity(),
                        CONNECTION_FAILURE_RESOLUTION_REQUEST);
            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }
        } else {
            Log.i(LOG_TAG, "Location services connection failed with code " +
                    connectionResult.getErrorCode());
        }
    }

    @Override
    public void onLocationChanged(Location location) {

        handleNewLocation(location);
    }

    private void handleNewLocation(Location location) {

        Log.i("TEST handleNewLocation", "Called handleNewLocation");
        // Returns the current adapter in use by the ListView supplied (mListView).
        LocationsAdapter adapter = (LocationsAdapter) mListView.getAdapter();
        adapter.setCurrentLocation(location);
        adapter.notifyDataSetChanged();
    }
}

MainActivity:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);

        CategoryAdapter adapter = new CategoryAdapter(this, getSupportFragmentManager());

        viewPager.setAdapter(adapter);

        // Keeps all 4 Fragments active at once
        viewPager.setOffscreenPageLimit(3);

        final SmartTabLayout tabLayout = (SmartTabLayout ) findViewById(R.id.viewpagertab);

        final LayoutInflater inflater = LayoutInflater.from(tabLayout.getContext());
        final Resources res = tabLayout.getContext().getResources();

        tabLayout.setCustomTabView(new SmartTabLayout.TabProvider() {

            @Override
            public View createTabView(ViewGroup container, int position, PagerAdapter adapter) {

                AppCompatImageView icon = (AppCompatImageView) inflater.inflate(R.layout.tab_bar_icon,container,
                        false);

                switch (position) {
                    case 0:
                        icon.setImageDrawable(res.getDrawable(R.drawable.ic_place_white_24dp));
                        break;
                    case 1:
                        icon.setImageDrawable(res.getDrawable(R.drawable.ic_restaurant_white_24dp));
                        break;
                    case 2:
                        icon.setImageDrawable(res.getDrawable(R.drawable.ic_wallpaper_white_24dp));
                        break;
                    case 3:
                        icon.setImageDrawable(res.getDrawable(R.drawable.ic_account_balance_white_24dp));
                        break;
                    default:
                        throw new IllegalStateException("Invalid position: " + position);
                }
                return icon;
            }
        });

        tabLayout.setViewPager(viewPager);

        // Fragment/Tab Titles
        final String[] mTitleNames = {"Locations", "Food", "Photos", "History"};

        // Default actionbar title
        setActionBarTitle(mTitleNames[0]);

        // Set actionbar title when tab is selected
        tabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                setActionBarTitle(mTitleNames[position]);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    public void setActionBarTitle(String title) {
        getSupportActionBar().setTitle(title);
    }
}

有没有人有任何可以和我分享的想法和/或代码,说明我如何解决这个问题?非常感谢!

更新

我可能应该更详细地解释一下。由于我对所有术语缺乏经验,我希望我的解释不难理解。

所以handleNewLocation()要调用onLocationChanged的全部目的,以便当用户的位置发生变化时,它会运行handleNewLocation()中的代码,该代码会获取用户的位置并运行它对于片段中上面的ArrayList中定义的设置坐标。这将导致两个位置之间的距离更新到例如6.5英里之外,依此类推,然后显示在ListView的TextView中。

LocationsAdapter是一个单独的java类,我可以在任何地方调用它。 - 所以我认为这不是问题的一部分。

我有数据类型Word,它由ArrayList使用,包含计算给定用户和位置坐标的代码,并将它们全部转换为DecimalFormat,以便在给定ListView中的TextViews中显示。

我认为我的问题是......我需要在Locations类中引用ArrayList。我需要引用ArrayList的确切实例和我将LocationsAdapter设置为的ListView,如:mListView.setAdapter(new LocationsAdapter(getActivity(), locations, mLocation));

我对Java的相对缺乏经验的形式是我不知道如何复制我的代码的所有当前状态,而是在MainActivity中获得所有位置获取代码,但仍然引用回{{1每个片段。

这有什么意义吗?我有点难以解释它。如果有帮助的话,我可以提供其他课程供参考吗?

1 个答案:

答案 0 :(得分:0)

假设您尝试获取位置的ListView,请参阅活动中的位置适配器

LocationsAdapter adapter = ((MainActivity) getActivity()).getLocationsAdapter();
listview.setAdapter(adapter);

现在,在Fragments中,你会得到像这样的适配器

{{1}}