旋转设备时,Android获取空的第一个活动是使用First Activity中的LoaderManager旁边的第二个活动和后退按钮

时间:2017-08-15 06:16:04

标签: android

问题的标题可能有点令人困惑,但作为初学者,我发现写一个准确的标题很难。现在我正在制作一个应用程序,从谷歌书籍api获取数据并在RecyclerView中显示它们。单击搜索按钮后,数据将加载到RecyclerView中。当我单击适配器的Individual Item时,它会打开DetailActivity。该应用程序正常工作如果我在MainActivity中旋转设备但是如果我在DetailActivity中旋转设备然后按回按钮,则MainActivity适配器为空。 MainActivity.java

package com.example.setha.booklisting;

import android.app.LoaderManager;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Books>> {

    public static final String LOG_TAG = MainActivity.class.getName();
    private static final int BOOKS_LOADER_ID = 1;
    private static final String BOOK_LIST = "book in list";

    private RecyclerView.Adapter adapter;
    private RecyclerView recyclerView;
    private TextView emptyView;
    private List<Books> books_list;
    private String book_searched = "";

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

        setContentView(R.layout.activity_main);

        Log.i(LOG_TAG, "TEST: onCreate() called ...");

        //calling adapter on a empty book list
        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(false);
        recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
        adapter = new MyAdapter(new ArrayList<Books>());
        recyclerView.setAdapter(adapter);

        Button searchButton = (Button) findViewById(R.id.button_search);

        searchButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.i(LOG_TAG, "TEST: search button clicked ...");
                book_searched = getSearchTerm();
                Log.i(LOG_TAG, "TEST: " + book_searched);
                if (!book_searched.equals("")) {

                    View loadingIndicator = findViewById(R.id.loading_spinner);
                    loadingIndicator.setVisibility(View.VISIBLE);

                    emptyView = (TextView) findViewById(R.id.emptyList);

                    getLoaderManager().restartLoader(BOOKS_LOADER_ID, null, MainActivity.this);

                    recyclerView.addOnItemTouchListener(
                            new RecyclerItemClickListener(MainActivity.this, recyclerView, new RecyclerItemClickListener.OnItemClickListener() {
                                @Override
                                public void onItemClick(View view, int position) {
                                    if (isOnline()) {
                                        Log.i(LOG_TAG, "TEST: detail activity clicked ...");
                                        Books book = books_list.get(position);
                                        Intent i = new Intent(MainActivity.this, DetailActivity.class);
                                        i.putExtra("imageLink", book.getImageUrl());
                                        i.putExtra("title", book.getTitle());
                                        i.putExtra("authors", book.getWriter());
                                        i.putExtra("description", book.getDescription());
                                        i.putExtra("infoLink", book.getInfoLink());
                                        startActivity(i);
                                    }
                                    else {
                                        Toast.makeText(MainActivity.this,"No Internet Connection",Toast.LENGTH_SHORT).show();
                                    }
                                }

                                @Override
                                public void onLongItemClick(View view, int position) {
                                    // do whatever
                                }
                            })
                    );
                }
            }
        });
        getLoaderManager();
        Log.i(LOG_TAG, "TEST: onCreate() finish ...");
    }

    //Update the adapter with books data
    private void updateUi(List<Books> books) {
        adapter = new MyAdapter(books);
        recyclerView.setAdapter(adapter);
    }

    @Override
    public Loader<List<Books>> onCreateLoader(int i, Bundle bundle) {
        Log.i(LOG_TAG, "TEST: onCreateLoader called ...");
        return new BookLoader(MainActivity.this, book_searched);
    }

    @Override
    public void onLoadFinished(Loader<List<Books>> loader, List<Books> books) {
        books_list = books;
        Log.i(LOG_TAG, "TEST: onLoaderFinished called ...");
        // Hide loading indicator because the data has been loaded
        View loadingIndicator = findViewById(R.id.loading_spinner);
        loadingIndicator.setVisibility(View.GONE);

        if (books == null) {
            emptyView.setText("No Books Found");
            emptyView.setVisibility(View.VISIBLE);
        }

        if (isOnline()) {
            //code if online
            if (books != null) {
                emptyView.setVisibility(View.GONE);
                updateUi(books);
            }
        } else {
            books = new ArrayList<>();
            updateUi(books);
            emptyView.setText("No Internet Connection");
            emptyView.setVisibility(View.VISIBLE);
        }

    }

    @Override
    public void onLoaderReset(Loader<List<Books>> loader) {
        Log.i(LOG_TAG, "TEST: onLoaderReset called ...");
        new MyAdapter(new ArrayList<Books>());
    }

    //helper method to check is device connected to internet or not
    public boolean isOnline() {
        ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = conMgr.getActiveNetworkInfo();

        if (netInfo == null || !netInfo.isConnected() || !netInfo.isAvailable()) {

            return false;
        }
        return true;
    }

    public String getSearchTerm() {
        EditText search_term = (EditText) findViewById(R.id.text_search_term);
        book_searched = search_term.getText().toString();
        book_searched = book_searched.replace(' ', '+');
        return book_searched;
    }
}

`

DetailActivity.java

    package com.example.setha.booklisting;

import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

import java.util.ArrayList;

public class DetailActivity extends AppCompatActivity {

    private String imageLink;
    private String title;
    private ArrayList<String> authors;
    private String details;
    private String infoLink;

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

        Bundle b = getIntent().getExtras();
        imageLink = b.getString("imageLink");
        title = b.getString("title");
        authors = b.getStringArrayList("authors");
        details = b.getString("description");
        infoLink = b.getString("infoLink");

        //code to show image of the book
        ImageView imageView = (ImageView) findViewById(R.id.img_thumbnail);
        Picasso.with(getBaseContext()).load(imageLink).into(imageView);

        TextView title_textView = (TextView) findViewById(R.id.text_title);
        title_textView.setText(title);

        //code to show authors of the book
        StringBuilder list_authors = new StringBuilder();
        for(String author : authors){
            list_authors.append(author + ", ");
        }
        TextView authors_textView = (TextView) findViewById(R.id.text_authors);
        authors_textView.setText(list_authors.toString().substring(0,list_authors.length()-2));

        TextView details_textView = (TextView) findViewById(R.id.text_description);
        details_textView.setText(details);

        Button moreInfo = (Button) findViewById(R.id.more_info_button);
        moreInfo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Uri webpage = Uri.parse(infoLink);
                Intent intent = new Intent(Intent.ACTION_VIEW, webpage);
                startActivity(intent);
            }
        });
    }
}

BookLoader

    package com.example.setha.booklisting;

import android.content.AsyncTaskLoader;
import android.content.Context;
import android.util.Log;

import java.util.List;

/**
 * Created by setha on 14-08-2017.
 */

public class BookLoader extends AsyncTaskLoader<List<Books>> {

    private String LOG_TAG = BookLoader.class.getSimpleName();
    private static final String GOOGLE_BOOKS_API_REQUEST_URL =
            "https://www.googleapis.com/books/v1/volumes?q=&maxResults=40&key=AIzaSyAsPSjnbNPMNf_eQ03by1iOalftZsbpu14";
    private String search_term;

    public BookLoader(Context context, String search_term) {
        super(context);
        this.search_term = search_term;
    }

    @Override
    protected void onStartLoading() {
        forceLoad();
    }

    @Override
    public List<Books> loadInBackground() {
        Log.i(LOG_TAG,"TEST: loadInBackground() called ...");

        String str = GOOGLE_BOOKS_API_REQUEST_URL;
        int index_to_add_search_term = str.indexOf("?q=");
        String url = str.substring(0,index_to_add_search_term + 3) + search_term + str.substring(index_to_add_search_term + 3);
        String[] urls = {url};
        Log.i(LOG_TAG,"TEST: url " + url);
        // Don't perform the request if there are no URLs, or the first URL is null.
        if (urls.length < 1 || urls[0] == null) {
            return null;
        }
        return Utils.fetchBooksData(urls[0]);
    }
}

2 个答案:

答案 0 :(得分:0)

执行重新创建的方向活动时,在这种情况下,您必须将整个数据保存在Bundle对象中。

有关方向的更多细节, View.OnLayoutChangeListener

答案 1 :(得分:0)

使用一堆日志消息我发现第二个Activity中的设备旋转后跟第一个Activity中的后退按钮设置加载器为null。所以当load设置为null时,我必须初始化一个加载器,这个调用loadInBackground方法来加载数据。 这是一个解决了我的问题的代码片段。

//this handle the case of recyclerview getting empty on rotation. This will reload the RecyclerView with previously fetched loader data without calling loadInBackground method
    if (getLoaderManager().getLoader(BOOKS_LOADER_ID) != null) {
        Log.i(LOG_TAG, "TEST: loader showing previously fetched data ...");
        getLoaderManager().initLoader(BOOKS_LOADER_ID, null, MainActivity.this);
        OnSingleBookTouchListener();
    }
    //this handle the case of loader being set to null if I rotate the device in DetailActivity (e.g if in MainActivity device is in Portrait mode and by clicking on any RecyclerView item I start DetailActivity. If I rotate the device in Detail activity to landscape mode and press back button to get back to MainActivity RecyclerView gets empty). So this will restart a loader.
    else {
        Log.i(LOG_TAG, "TEST: LoaderManager reloaded ...");
        if (!book_searched.equals("")) {
            getLoaderManager().initLoader(BOOKS_LOADER_ID, null, MainActivity.this);
            OnSingleBookTouchListener();
        }
    }
    Log.i(LOG_TAG, "TEST: onCreate() finish ...");
}