java - 我如何在后台线程中运行 onNavigationItemSelected 方法

标签 java android multithreading navigation-drawer

当我编写 mNavigationView.setNavigationItemSelectedListener(this); 时,应用程序崩溃在代码中 如果未添加,则会删除导航栏中该项目的功能。我应该在后台线程中运行哪种方法以减少对主线程的影响。

import android.app.Activity;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.SwipeRefreshLayout;
import android.content.Context;
import android.content.Intent;

import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;

import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;

import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;


import com.eggheadgames.aboutbox.AboutConfig;
import com.eggheadgames.aboutbox.IAnalytic;
import com.eggheadgames.aboutbox.IDialog;
import com.eggheadgames.aboutbox.activity.AboutActivity;


import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


public class EarthquakeActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener, SwipeRefreshLayout.OnRefreshListener, LoaderManager.LoaderCallbacks<List<Earthquake>>, NavigationView.OnNavigationItemSelectedListener {
    public static final String MyPrefs = "MyPrefs";
    private DrawerLayout mdrawerlayout;
    private ActionBarDrawerToggle mToogle;
    /** URL for earthquake data from the USGS dataset */
    private static final String USGS_REQUEST_URL =     "https://earthquake.usgs.gov/fdsnws/event/1/query";

    /**
     * Constant value for the earthquake loader ID. We can choose any integer.
     * This really only comes into play if you're using multiple loaders.
     */
    private static final int EARTHQUAKE_LOADER_ID = 1;

    /** Adapter for the list of earthquakes */
    private EarthquakeAdapter mAdapter;

    /** TextView that is displayed when the list is empty */
    private TextView mEmptyStateTextView;

    SwipeRefreshLayout swipe;

    private static final String LOG_TAG = EarthquakeActivity.class.getSimpleName();


    private ListView earthquakeListView;

    private static final String TWITTER_USER_NAME = "vaibhav_khulbe";
    private static final String WEB_HOME_PAGE = "https://about.me/vaibhav_khulbe";
    private static final String APP_PUBLISHER = "https://play.google.com/store/apps/developer?id=Vaibhav%20Khulbe&hl=en";
    private static final String EMAIL_ADDRESS = "khulbevaibhavdev@gmail.com";
    private static final String EMAIL_SUBJECT = "Quake Info app acknowledgements and/or issues";
    private static final String EMAIL_BODY = "Please explain your experience with this app here...This may include bugs" +
            " or issues you may be facing or what you liked about the app along with improvements. :) (MAKE SURE to clear out these lines before sending the mail to us)";

    Toolbar toolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.earthquake_activity);
        mdrawerlayout=(DrawerLayout)findViewById(R.id.drawer);
        mToogle=new ActionBarDrawerToggle(this,mdrawerlayout,R.string.open,R.string.close);
        mdrawerlayout.addDrawerListener(mToogle);
        mToogle.syncState();
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        NavigationView mNavigationView=(NavigationView)findViewById(R.id.navigation_view);
        mNavigationView.setNavigationItemSelectedListener(this);

        swipe = findViewById(R.id.swiperefresh);
        swipe.setOnRefreshListener(this);
        swipe.setColorSchemeColors(getResources().getColor(R.color.colorAccent));

        /* Start the intro only once */
        SharedPreferences sp = getSharedPreferences(MyPrefs, Context.MODE_PRIVATE);
        if (!sp.getBoolean("first", false)) {
            SharedPreferences.Editor editor = sp.edit();
            editor.putBoolean("first", true);
            editor.apply();
            Intent intent = new Intent(this, IntroActivity.class);
            startActivity(intent);
        }

        //Call and launch About activity
        initAboutActivity();

        // Find a reference to the {@link ListView} in the layout
        earthquakeListView = (ListView) findViewById(R.id.list);

        mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
        earthquakeListView.setEmptyView(mEmptyStateTextView);

        // Create a new adapter that takes an empty list of earthquakes as input
        mAdapter = new EarthquakeAdapter(this, new ArrayList<Earthquake>());

        // Set the adapter on the {@link ListView}
        // so the list can be populated in the user interface
        earthquakeListView.setAdapter(mAdapter);

        // Obtain a reference to the SharedPreferences file for this app
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        // And register to be notified of preference changes
        // So we know when the user has adjusted the query settings
        prefs.registerOnSharedPreferenceChangeListener(this);

        // Set an item click listener on the ListView, which sends an intent to a web browser
        // to open a website with more information about the selected earthquake.
        earthquakeListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                // Find the current earthquake that was clicked on
                Earthquake currentEarthquake = mAdapter.getItem(position);

                // Convert the String URL into a URI object (to pass into the Intent constructor)
                Uri earthquakeUri = Uri.parse(currentEarthquake.getUrl());

                // Create a new intent to view the earthquake URI
                Intent websiteIntent = new Intent(Intent.ACTION_VIEW, earthquakeUri);

                // Send the intent to launch a new activity
                startActivity(websiteIntent);
            }
        });
        getSupportLoaderManager().initLoader(EARTHQUAKE_LOADER_ID, null, this);

    }



    /*Code to launch About activity */
    public void initAboutActivity()
    {
        /* Create About activity */
        AboutConfig aboutConfig = AboutConfig.getInstance();
        aboutConfig.appName = getString(R.string.app_name);
        aboutConfig.appIcon = R.mipmap.ic_launcher;
        aboutConfig.version = "1.0.0";
        aboutConfig.author = "Vaibhav Khulbe";
        aboutConfig.aboutLabelTitle = "About";
        aboutConfig.packageName = getApplicationContext().getPackageName();

        aboutConfig.appPublisher = APP_PUBLISHER;

        aboutConfig.twitterUserName = TWITTER_USER_NAME;
        aboutConfig.webHomePage = WEB_HOME_PAGE;


        aboutConfig.dialog = new IDialog() {
            @Override
            public void open(AppCompatActivity appCompatActivity, String url, String tag) {
                // handle custom implementations of WebView. It will be called when user click to web items. (Example: "Privacy", "Acknowledgments" and "About")
            }
        };

        aboutConfig.analytics = new IAnalytic() {
            @Override
            public void logUiEvent(String s, String s1) {
                // handle log events.
            }

            @Override
            public void logException(Exception e, boolean b) {
                // handle exception events.
            }
        };
        // set it only if aboutConfig.analytics is defined.
        aboutConfig.logUiEventName = "Log";

        // Contact Support email details
        aboutConfig.emailAddress = EMAIL_ADDRESS;
        aboutConfig.emailSubject = EMAIL_SUBJECT;
        aboutConfig.emailBody = EMAIL_BODY;


        aboutConfig.shareMessage = getString(R.string.share_message);
        aboutConfig.sharingTitle = getString(R.string.sharing_title);

    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
        if (key.equals(getString(R.string.settings_min_magnitude_key)) ||
                key.equals(getString(R.string.settings_order_by_key))){
            // Clear the ListView as a new query will be kicked off
            mAdapter.clear();

            // Hide the empty state text view as the loading indicator will be displayed
            mEmptyStateTextView.setVisibility(View.GONE);

            // Show the loading indicator while new data is being fetched
            View loadingIndicator = findViewById(R.id.loading_indicator);
            loadingIndicator.setVisibility(View.VISIBLE);

            // Restart the loader to requery the USGS as the query settings have been updated
            getSupportLoaderManager().restartLoader(EARTHQUAKE_LOADER_ID, null, this);
        }
    }

    @Override
    public Loader<List<Earthquake>> onCreateLoader(int i, Bundle bundle) {

         SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        String minMagnitude = sharedPrefs.getString(
                getString(R.string.settings_min_magnitude_key),
                getString(R.string.settings_min_magnitude_default));

        String orderBy = sharedPrefs.getString(
                getString(R.string.settings_order_by_key),
                getString(R.string.settings_order_by_default)
        );

        String region = sharedPrefs.getString(
                getString(R.string.settings_narrow_by_region_key),
                getString(R.string.settings_narrow_by_region_default)
        );

        String radius = sharedPrefs.getString(
                getString(R.string.settings_maximum_radius_key),
                getString(R.string.settings_maximum_radius_default)
        );

        List<Country> countries = new ArrayList<>();

        try {
            countries = Utils.generateCountryList(this);
        } catch (IOException e) {
            e.printStackTrace();
        }

        Double latitude = 0.0;
        Double longitude = 0.0;
        for (Country country : countries) {
            if(country.getName().equalsIgnoreCase(region)){
                latitude = country.getLatitude();
                longitude = country.getLongitude();
            }
        }

        Uri baseUri = Uri.parse(USGS_REQUEST_URL);
        Uri.Builder uriBuilder = baseUri.buildUpon();

        uriBuilder.appendQueryParameter("format", "geojson");
        uriBuilder.appendQueryParameter("limit", "100");
        uriBuilder.appendQueryParameter("minmag", minMagnitude);
        uriBuilder.appendQueryParameter("orderby", orderBy);

        if(latitude != 0.0 && longitude != 0.0){
            uriBuilder.appendQueryParameter("latitude", String.valueOf(latitude.intValue()));
            uriBuilder.appendQueryParameter("longitude", String.valueOf(longitude.intValue()));
            uriBuilder.appendQueryParameter("maxradius", radius);
        }

        String url = uriBuilder.toString();
        return new EarthquakeLoader(this, url);
    }




    @Override
    public void onLoadFinished(Loader<List<Earthquake>> loader, List<Earthquake> earthquakes) {
        swipe.setRefreshing(false);

        // Hide loading indicator because the data has been loaded
        View loadingIndicator = findViewById(R.id.loading_indicator);
        loadingIndicator.setVisibility(View.GONE);



        if (earthquakes != null && !earthquakes.isEmpty()) {
            this.showResults(earthquakes);
        } else {
            this.hideResults();
        }
    }

    @Override
    public void onLoaderReset(Loader<List<Earthquake>> loader) {
        // Loader reset, so we can clear out our existing data.
        mAdapter.clear();
    }

    /**
     * method to show results
     */
    private void showResults(List<Earthquake> earthquakeList) {
        mAdapter.clear();
        earthquakeListView.setVisibility(View.VISIBLE);
        mEmptyStateTextView.setVisibility(View.GONE);
        mAdapter.setNotifyOnChange(false);
        mAdapter.setNotifyOnChange(true);
        mAdapter.addAll(earthquakeList);
    }

    /**
     * method to hide results also checks internet connection
     */
    private void hideResults() {
        earthquakeListView.setVisibility(View.GONE);
        mEmptyStateTextView.setVisibility(View.VISIBLE);
        // Get a reference to the ConnectivityManager to check state of network connectivity
        ConnectivityManager connMgr = (ConnectivityManager)
                getSystemService(Context.CONNECTIVITY_SERVICE);

        // Get details on the currently active default data network
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();

        if (networkInfo != null && networkInfo.isConnected()) {
            mEmptyStateTextView.setText(R.string.no_earthquakes);
            Log.e(LOG_TAG, "no earthquakes data");

        } else {
            mEmptyStateTextView.setText(R.string.no_internet_connection);
            Log.e(LOG_TAG, "no internet");
        }
    }



    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (mToogle.onOptionsItemSelected(item)){
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
    @Override
    public void onRefresh() {
        getSupportLoaderManager().restartLoader(EARTHQUAKE_LOADER_ID, null, this);
        Toast.makeText(this, R.string.list_refreshed, Toast.LENGTH_SHORT).show();

    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            Intent settingsIntent = new Intent(this, SettingsActivity.class);
            startActivity(settingsIntent);
            return true;
        }
        if (id == R.id.action_about) {
            Intent actionIntent = new Intent(this, AboutActivity.class);
            startActivity(actionIntent);
            return true;
        }
        if (id == R.id.action_did_you_feel_it){

            Intent feelItIntent = new Intent(this, DidYouFeel.class);
            startActivity(feelItIntent);
            return true;
        }
        if (id == R.id.action_more_apps){

            Uri uri = Uri.parse( "https://play.google.com/store/apps/developer?id=Vaibhav+Khulbe" );
            startActivity( new Intent( Intent.ACTION_VIEW, uri ) );
        }
        if (id == R.id.fork_project){

            Uri uri = Uri.parse( "https://github.com/Kvaibhav01/Quake-Info" );
            startActivity( new Intent( Intent.ACTION_VIEW, uri ) );
        }

        if (id == R.id.notification){

            Intent notificationIntent = new Intent(this, EarthquakeNotification.class);
            startActivity(notificationIntent);
        }
        return true;
    }

}

我认为可以通过在后台线程中运行该方法来完成,但我不确定如何做到这一点。感谢您的帮助

最佳答案

您可以使用如下示例代码:

 ((MainActivity)context).runOnUiThread(new Runnable() {
    public void run() {
      //run another thread 
    }
});

或者如果您熟悉RxJava,您可以使用它。 考虑到大多数时候您应该执行一个在单击后调用它的函数,而不是 click 方法。

关于java - 我如何在后台线程中运行 onNavigationItemSelected 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58285954/

相关文章:

java - 我们能得到给定日期对象的模式吗

java - 计数功能不完整

android - 如何在nutiteq上计算跟踪时的平均距离、速度和时间

java - AH00052 : child pid 2453 exit signal Segmentation fault (11)

java - MySQL JDBC 连接错误

c# - Unity - Gui 按钮问题 (Android)

android - 从 Activity 返回时没有当前的 openGL 上下文?

java - 多线程-奇偶数

python - 通过两个单独的线程访问全局字典返回不同的结果

Java 线程 : According to sun there are only four stages in thread life cycle