Search code examples
androidjsonandroid-asynctaskcoordinatesmotionevent

Pass MotionEvent ActionDown coordinates to inner class (AsyncTask)


as the title says, I want to be able to pass the coordinates given on ACTION_DOWN to the onPostExecute method of my AsyncTask inner class. I have been trying to do this for the past two days without success. How do I go about this? Any help is appreciated :)

Here is my code:

package io.music.ui.settings;

import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.annotation.Nullable;

import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


import io.music.R;
import io.music.ui.base.BaseFragment;
import io.music.ui.main.MainActivity;

import android.view.MotionEvent;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.RequestQueue;
import com.android.volley.toolbox.JsonArrayRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import static android.R.attr.x;


public class SettingsFragment extends BaseFragment {

    public static final int CONNECTION_TIMEOUT = 10000;
    public static final int READ_TIMEOUT = 15000;
    private RecyclerView mRVFishPrice;
    private AdapterFish mAdapter;
    public float x = 0.95f;
    //String xx = String.format("%.2f", x);
    public float y = 0;
    float x1, x2, y1, y2;

    List<DataFish> data=new ArrayList<>();
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        final View view = inflater.inflate(R.layout.fragment_settings, container, false);

        view.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {

                int action = event.getAction();
                if (action == MotionEvent.ACTION_DOWN) {

                    x = 2f * (event.getX() / v.getWidth()) - 1f;
                    y = -2f * (event.getY() / v.getHeight()) + 1f;

                    //x1 = x - 0.1f;
                    //x2 = x + 0.1f;
                    //y1 = y - 0.1f;
                    //y2 = y + 0.1f;
                    TextView textView = (TextView) getView().findViewById(R.id.textView2);
                    textView.setText(String.format("%.2f", x));
                    TextView textView2 = (TextView) getView().findViewById(R.id.textView3);
                    textView2.setText(String.format("%.2f", y));
                }

                mRVFishPrice = (RecyclerView) view.findViewById(R.id.fishPriceList);
                mAdapter = new AdapterFish(getActivity(), data);
                mRVFishPrice.setAdapter(mAdapter);
                mRVFishPrice.setLayoutManager(new LinearLayoutManager(getActivity()));

                return false;
            }

        });


        new AsyncFetch().execute();

        return view;
    }




    private class AsyncFetch extends AsyncTask<String, String, String> {
        ProgressDialog pdLoading = new ProgressDialog(getActivity());
        HttpURLConnection conn;
        URL url = null;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            //this method will be running on UI thread
            pdLoading.setMessage("\tLoading...");
            pdLoading.setCancelable(false);
            pdLoading.show();

        }

        @Override
        protected String doInBackground(String... params) {
            try {

                // Enter URL address where your json file resides
                // Even you can make call to php file which returns json data
                url = new URL("http://example.com/Subjects2.php");

            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return e.toString();
            }
            try {

                // Setup HttpURLConnection class to send and receive data from php and mysql
                conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(READ_TIMEOUT);
                conn.setConnectTimeout(CONNECTION_TIMEOUT);
                conn.setRequestMethod("POST");

                // setDoOutput to true as we recieve data from json file

                conn.setDoOutput(true);


            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
                return e1.toString();
            }

            try {

                int response_code = conn.getResponseCode();

                // Check if successful connection made
                if (response_code == HttpURLConnection.HTTP_OK) {

                    // Read data sent from server
                    InputStream input = conn.getInputStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(input));
                    StringBuilder result = new StringBuilder();
                    String line;

                    while ((line = reader.readLine()) != null) {
                        result.append(line);
                    }

                    // Pass data to onPostExecute method
                    return (result.toString());

                } else {

                    return ("unsuccessful");
                }

            } catch (IOException e) {
                e.printStackTrace();
                return e.toString();
            } finally {
                conn.disconnect();
            }


        }


        @Override
        public void onPostExecute(String result) {

            //this method will be running on UI thread


            pdLoading.dismiss();


            pdLoading.dismiss();
            try {

                JSONArray jArray = new JSONArray(result);

                // Extract data from json and store into ArrayList as class objects
                for(int i=0;i<jArray.length();i++){

                    JSONObject json_data = jArray.getJSONObject(i);

                    String xx= String.format("%.2f", x);
                    if(json_data.getString("X").equals(xx) ) {
                        DataFish fishData = new DataFish();

                        fishData.fishName = json_data.getString("SongName");
                        fishData.catName = json_data.getString("X");
                        fishData.sizeName = json_data.getString("Y");

                        data.add(fishData);

                    }
                }

                // Setup and Handover data to recyclerview


            } catch (JSONException e) {
                Toast.makeText(getActivity(), e.toString(), Toast.LENGTH_LONG).show();
            }

        }

    }


}

EDIT: I also want to specify that I am trying to get the variables x and y to the onPostExecute method and I have put a value for x just to test if the json output is correct. I want the x coordinate to come from the TouchListener.


Solution

  • you should indeed load the json file only once, when the activity/fragment loads, but you may want to display some progress bar while the file loads and the fragment isn't ready yet to accept user touches. (see this)

    When the file finishes downloading, and you go into onPostExecute:

    1. Change jArray to be a class field, and store new JSONArray(result); in it so it can be accessed from anywhere in the class.
    2. hide your progress-bar, and display the real layout to the user.

    Then in your onTouch implementation, use the value in jArray to perform that for loop that populates your RecyclerView (move that code from onPostExecute to the onTouch listener)