使用Bundle在类和片段之间传递数据

时间:2016-09-10 17:00:02

标签: java android android-fragments bundle

我正在尝试使用Bundle将Query类中的数据(我在Query类中设置参数“)传递给Fragment类之一(我需要在此片段类中使用”getArguments()“ ),但是我已经使用日志进行了一些基本调试,并且已经看到在实现Query类之前创建了片段。因此,当我从片段类中获取“getArguments”时,它为NULL,因为尚未在Query类中设置参数。

我想在片段类中使用Query类中的数据。任何人都可以告诉我该做什么? 你可能会说我对Android比较新,也不太了解片段。

上下文:我正在开发一个Weather应用程序。我今天有三个片段,明天和七天预测(灵感来自标签布局Google Now的天气卡)。我还有一个Query类,用于查询JSON数据的在线API以及主要的活动类。

MainActivity类:

package com.example.desno.testnavtablayout;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;

import org.json.JSONObject;

import java.util.concurrent.ExecutionException;

import tabFragments.SevenDayFragment;
import tabFragments.TodayFragment;
import tabFragments.TomorrowFragment;

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

    public Double latitude;
    public Double longitude;

    private static final String API_KEY = "&APPID=";                    // Placeholder for the openweathermaps API key
    private static final String QUERY_URL = "http://api.openweathermap.org/data/2.5/weather?q=";        // Placeholder for the openweathermaps URL
    private static final String UNITS = "&mode=json&units=metric&cnt=7";                                // Placeholder specifying the data type and unit type of this data being retrieved

    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a
     * {@link FragmentPagerAdapter} derivative, which will keep every
     * loaded fragment in memory. If this becomes too memory intensive, it
     * may be best to switch to a
     * {@link android.support.v4.app.FragmentStatePagerAdapter}.
     */
    private SectionsPagerAdapter mSectionsPagerAdapter;

    /**
     * The {@link ViewPager} that will host the section contents.
     */
    private ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.container);
        mViewPager.setAdapter(mSectionsPagerAdapter);
        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(mViewPager);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);


        // Initialise the Android location manager to get the users current location automatically:
        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        String provider = locationManager.getBestProvider(new Criteria(), false);
        // Handle what happens if the user doesn't grant permission for location (this has been generated automatically):
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
        {
            //  TODO: Consider calling
            //  ActivityCompat#requestPermissions
            //  here to request the missing permissions, and then overriding
            //  public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
            //  to handle the case where the user grants the permission. See the documentation
            //  for ActivityCompat#requestPermissions for more details.
            return;
        }
        Location location = locationManager.getLastKnownLocation(provider);     // Get last known location of the user

        latitude = location.getLatitude();                               // Storage variable for the users latitude
        longitude = location.getLongitude();                             // Storage variable for the users logitude

        Query query = new Query();                                              // Create a new instance of the Query class, pass it the URL with the values of the users GPS coordinates embedded and execute it
        query.execute("http://api.openweathermap.org/data/2.5/weather?lat=" + String.valueOf(latitude) + "&lon=" + String.valueOf(longitude) + UNITS + API_KEY);
    }

    // Receives the value of searchLocationQuery and manipulates it
    private JSONObject queryForRequestedLocation(String location)
    {
        String parsedData = "";                                                                 // Placeholder for URL with embedded search value
        try
        {
            parsedData = new Query().execute(QUERY_URL + location + UNITS + API_KEY).get();     // Pass the URL with embedded search, units and API key to the Query class for parsing
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        catch (ExecutionException e)
        {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        private static final String ARG_SECTION_NUMBER = "section_number";

        public PlaceholderFragment() {
        }

        /**
         * Returns a new instance of this fragment for the given section
         * number.
         */
        /*public static PlaceholderFragment newInstance(int sectionNumber) {
            PlaceholderFragment fragment = new PlaceholderFragment();
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, sectionNumber);
            fragment.setArguments(args);
            return fragment;
        }*/

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.content_main, container, false);
            TextView textView = (TextView) rootView.findViewById(R.id.section_label);
            textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));

            return rootView;
        }
    }

    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {

            // getItem is called to instantiate the fragment for the given page.
            // Return a PlaceholderFragment (defined as a static inner class below).
            switch(position){
                case 0 : return TodayFragment.newInstance();
                case 1 : return TomorrowFragment.newInstance();
                case 2 : return SevenDayFragment.newInstance();
                // default: return MyFragment.newInstance();
/* It is better to use default so that it always returns a fragment and no problems would ever occur */
            }
            return null; //if you use default, you would not need to return null


            /*// getItem is called to instantiate the fragment for the given page.
            // Return a PlaceholderFragment (defined as a static inner class below).
            return PlaceholderFragment.newInstance(position + 1);*/
        }

        @Override
        public int getCount() {
            // Show 3 total pages.
            return 3;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
                case 0:
                    return "SECTION 1";
                case 1:
                    return "SECTION 2";
                case 2:
                    return "SECTION 3";
            }
            return null;
        }
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_camera) {
            // Handle the camera action
        } else if (id == R.id.nav_gallery) {

        } else if (id == R.id.nav_slideshow) {

        } else if (id == R.id.nav_manage) {

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

}

查询类:

package com.example.desno.testnavtablayout;

/**
 * Created by desno on 30/05/2016.
 */

import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;

import org.json.JSONObject;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import tabFragments.TodayFragment;

public class Query extends AsyncTask<String, Void, String>
{
    private static String locationName;

    // Query for the data
    @Override
    protected String doInBackground(String... urls)
    {
        String queryResult = "";                                                        // Storage variable for the json data
        URL url;                                                                        // URL is used as address to the data needed
        HttpURLConnection urlConnection = null;                                         // Make a remote request using the HttpURLConnection class

        // Surround with try/catch so the application doesn't crash in the case of an exception such as no internet connection
        try
        {
            url = new URL(urls[0]);                                                     // Create a new URL from what is supplied
            urlConnection = (HttpURLConnection) url.openConnection();                   // Establish a URL connection and pass it to a HttpURLConnection
            InputStream inputStream = urlConnection.getInputStream();                   // Get an InputStream from the HttpURLConnection
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);   // Create an InputStreamReader to read the InputStream
            int inputStreamData = inputStreamReader.read();                             // Store the data from the InputStreamReader

            // Need a while loop because when InputStreamReader is finished the result is equal to -1
            while (inputStreamData != -1)
            {
                char current = (char) inputStreamData;
                queryResult += current;
                inputStreamData = inputStreamReader.read();
            }

            return queryResult;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    // Parse the json data
    @Override
    protected void onPostExecute(String queryResult)
    {
        super.onPostExecute(queryResult);

        try
        {
            JSONObject jsonObject = new JSONObject(queryResult);                        // Create a new json object and pass it the data from the queryResult string
            JSONObject weatherData = new JSONObject(jsonObject.getString("main"));      // Create another json object to contain more specific weather data such as all the data within the "main" braces

            Double temperature = Double.parseDouble(weatherData.getString("temp"));     // Grab the temperature value, which is currently stored as a string within the weatherData object, and store it as a double labeled "temperature"

            locationName = jsonObject.getString("name");                         // Create storage variable for the location name

            Bundle args = new Bundle();
            args.putString("LocationName", locationName);
            TodayFragment todayFragment = new TodayFragment();
            todayFragment.setArguments(args);
            Log.i("Loc working in query=", args.toString());

           // MainActivity.temperatureTextView.setText(temperature.toString()+ " °C");    // Set the value of the temperature TextView equal to the value of the temperature variable and add a degrees celsius symbol
           // MainActivity.locationTextView.setText(locationName);                        // Set the value of the location TextView equal to the value of the locationName variable

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

TodayFragment类:

package tabFragments;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import com.example.desno.testnavtablayout.Query;
import com.example.desno.testnavtablayout.R;

import java.security.PublicKey;

/**
 * Created by desno on 09/09/2016.
 */
public class TodayFragment extends Fragment
{
    Button ClickMe;
    TextView tv;
    public String loc;

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

        Bundle bundle = this.getArguments();
        if (bundle == null)
        {
            //loc = bundle.getString("LocationName");
            Log.i("Bundle is STILL null", "TodayFrag OnCreate()");
        }
    }

    public TodayFragment()
    {

    }

    public static TodayFragment newInstance()
    {
        TodayFragment fragment = new TodayFragment();
        return fragment;
    }

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

        ClickMe = (Button) rootView.findViewById(R.id.button);
        tv = (TextView) rootView.findViewById(R.id.textView2);

        ClickMe.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                if(tv.getText().toString().contains("Hello"))
                {
                    tv.setText("Hi");
                }
                else tv.setText("Hello");
            }
        });

        /*String strtext = getArguments().getString("LocationName");
        if (strtext != null)
        {
            Log.i("Location=", strtext.toString());
        }*/
        Bundle bundle = this.getArguments();
        if (bundle == null)
        {
            //loc = bundle.getString("LocationName");
            Log.i("Bundle is null", "TodayFrag OnCreateView()");
        }
        return rootView;
    }

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

        Bundle bundle = this.getArguments();
        if (bundle == null) {
            //String i = bundle.getString("LocationName");
            Log.i("Bundle is null", "in TodayFrag onActivityCreated()");
        }
    }

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

        Bundle bundle = this.getArguments();
        if (bundle == null)
        {
            //loc = bundle.getString("LocationName");
            Log.i("Bundle is STILL null", "TodayFrag OnViewStateRestored()");
        }
    }
}

2 个答案:

答案 0 :(得分:0)

在您知道已创建片段后尝试运行Query。这是两个想法......

一种可能性是将查询参数传递给TodayFragment / TomorrowFragment / SevenDayFragment并让他们调用自己的查询。像这样的东西:

public class TodayFragment extends Fragment {
    private static final String BUNDLE_KEY_SOME_PARAM = "BUNDLE_KEY_SOME_PARAM";

    public static TodayFragment newInstance(String someParam) {
        final Bundle creationArgs = new Bundle();
        creationArgs.putString(BUNDLE_KEY_SOME_PARAM, someParam);

        final TodayFragment instance = new TodayFragment();
        instance.setArguments(creationArgs);

        return instance;
    }

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

        // run the Query locally
        final String someParam = getArguments().getString(BUNDLE_KEY_SOME_PARAM);

        new Query().execute(someParam);
    }
}

如果您不喜欢将这种类型的逻辑放在您的片段中,您可以让他们回调MainActivity以根据需要运行查询。也许是这样的:

interface QueryExecutor {
    void query(String someParam);
}

interface QueryResultListener {
    void results(String someResult);
}

public class TodayFragment extends Fragment implements QueryResultListener {
    private static final String BUNDLE_KEY_SOME_PARAM = "BUNDLE_KEY_SOME_PARAM";

    public static TodayFragment newInstance(String someParam) {
        final Bundle creationArgs = new Bundle();
        creationArgs.putString(BUNDLE_KEY_SOME_PARAM, someParam);

        final TodayFragment instance = new TodayFragment();
        instance.setArguments(creationArgs);

        return instance;
    }

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

        final QueryExecutor queryExecutor = (QueryExecutor)getActivity();

        final String someParam = getArguments().getString(BUNDLE_KEY_SOME_PARAM);

        queryExecutor.query(someParam);
    }

    @Override
    public void results(String someResult) {
        // handle the query results...
    }
    …
}

我希望有所帮助。

答案 1 :(得分:0)

为什么不简单地从Fragment中进行查询?我想这将是最简单的解决方案。