我正在尝试将设备的当前位置传递给我的asynctask类,以便在我的recyclerview中填充列表之前根据它们的距离过滤掉列表。无论何时我运行此代码,我得到一个空列表,我当前的位置为空。难道我做错了什么?它仅在我手动输入位置坐标时才有效。
这是我的清单中的权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.example.kwao.roninsnradars.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
这包含我的Fragment和My AsyncTask类:
public class MyListFragment extends Fragment implements SearchView.OnQueryTextListener,GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener{
// TODO: Rename parameter arguments, choose names that match
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private static final String ARG_PARAM3 = "param3";
private int mParam1;
private List<Data> totalData = new ArrayList<>();
private BackendlessCollection<Data> Data;
private MyRecyclerAdapter adapter;
private View view;
public RecyclerView recyclerView;
RecyclerView.LayoutManager gridLayoutManager, linearLayoutManager;
private ProgressDialog progressDialog;
private SwipeRefreshLayout swipeRefreshLayout;
private MyRecyclerAdapter.OnListFragmentInteractionListener mListener;
private GoogleApiClient mGoogleApiClient;
private Location mLocation;
private LocationRequest locationRequest;
private Double mLatitude;
private Double mLongitude;
public MyListFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @return A new instance of fragment MyListFragment.
*/
// TODO: Rename and change types and number of parameters
public static MyListFragment newInstance(int param1) {
MyListFragment fragment = new MyListFragment();
Bundle args = new Bundle();
args.putInt(ARG_PARAM1, param1);
//args.putDouble(ARG_PARAM2, param2);
//args.putDouble(ARG_PARAM3, param3);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setHasOptionsMenu(true);
if (view != null) {
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null)
parent.removeView(view);
}
// Defining Linear Layout Manager
linearLayoutManager = new LinearLayoutManager(getContext());
view = inflater.inflate(R.layout.Data_fragment_list_view, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(linearLayoutManager);
try {
Data = new FindDataAndPopulate(mLatitude,mLongitude).execute().get(30, TimeUnit.SECONDS);
} catch ( CancellationException | ExecutionException | InterruptedException | TimeoutException e ){
Toast.makeText( getActivity(), "Failed to load Data: " + e.getMessage(), Toast.LENGTH_LONG ).show();
}
swipeRefreshLayout = (SwipeRefreshLayout)view.findViewById(R.id.refresh_layout);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
clear();
try {
Data = new FindDataAndPopulate(mLatitude,mLongitude).execute().get(30, TimeUnit.SECONDS);
} catch (CancellationException | ExecutionException | InterruptedException | TimeoutException e) {
Toast.makeText(getActivity(), "Failed to load Data: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
refreshItems();
}
});
mGoogleApiClient = new GoogleApiClient.Builder(getContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
return view;
}
public void clear() {
totalData.clear();
adapter.notifyDataSetChanged();
}
private void addMore(BackendlessCollection<Data> next) {
totalData.addAll(next.getCurrentPage());
adapter.notifyDataSetChanged();
}
private void refreshItems() {
onItemsLoadComplete();
}
void onItemsLoadComplete() {
adapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Inflate the menu; this adds items to the action bar if it is present.
inflater.inflate(R.menu.main_page, menu);
final MenuItem item = menu.findItem(R.id.search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setQueryHint("Search Data Around You");
searchView.setOnQueryTextListener(this);
MenuItemCompat.setOnActionExpandListener(item,new MenuItemCompat.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
adapter.setFilter(totalData);
return true;
}
});
}
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
final List<Data> filteredRoninList = filter(totalData, newText);
adapter.setFilter(filteredRoninList);
return true;
}
private List<Data> filter(List<Data> areaData, String query) {
query = query.toLowerCase();
final List<Data> filteredDataList = new ArrayList<>();
for (Data ronin : areaData) {
final String text = ronin.getRoninName().toLowerCase();
if (text.contains(query)) {
filteredDataList.add(ronin);
}
}
return filteredDataList;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof MyRecyclerAdapter.OnListFragmentInteractionListener) {
mListener = (MyRecyclerAdapter.OnListFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
@Override
public void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
public void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(getContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLocation != null) {
mLatitude = mLocation.getLatitude();
mLongitude = mLocation.getLongitude();
} else {
Toast.makeText(getContext(), "Location not Detected", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onConnectionSuspended(int i) {
Log.i("Pius", "Connection Suspended");
mGoogleApiClient.connect();
}
@Override
public void onLocationChanged(Location location) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.i("Pius", "Connection failed. Error: " + connectionResult.getErrorCode());
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public class FindDataAndPopulate extends AsyncTask<Void, Void,BackendlessCollection<Data>>
{
Double myLatitude;
Double myLongitude;
public FindDataAndPopulate(Double myLatitude,Double myLongitude){
this.myLatitude = myLatitude;
this.myLongitude = myLongitude;
}
private Context context ;
@Override
protected BackendlessCollection<Data> doInBackground(Void... params) {
String query = "distance( %f, %f, location.latitude, location.longitude ) < mi(5) = true";
String whereClause = String.format( query, mLatitude, mLongitude );
BackendlessDataQuery dataQuery = new BackendlessDataQuery( whereClause );
QueryOptions queryOptions = new QueryOptions();
queryOptions.addRelated( "location" );
dataQuery.setQueryOptions( queryOptions );
Data = Backendless.Data.of(Data.class ).find(dataQuery);
return Data;
}
@Override
protected void onPreExecute() {
// progressDialog = ProgressDialog.show(context, "", "Loading...", true);
}
@Override
protected void onPostExecute(BackendlessCollection<Data> DataBackendlessCollection) {
Data = DataBackendlessCollection;
adapter = new MyRecyclerAdapter(getContext(),totalData, mListener);
recyclerView.setAdapter(adapter);
addMore(Data);
}
};
}
答案 0 :(得分:0)
问题在于:
mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
如果设置中未启用位置, getLastLocation()
将不会立即返回 结果。这就是为什么你不应该依赖getLastKnownLocation()
获取最近的位置。
您可以做的是:如果location返回null - 您需要创建LocationRequest
并检查位置设置。如果在设置中启用了位置,则需要以一定间隔调用requestLocationUpdates
。获得onLocationUpdated
中的最新位置后,请停止位置更新,并根据该位置执行任何操作。
需要注意的另一件事是:不要为Asynctask
使用嵌套类,因为它们可以轻松创建memory leaks。