重新创建活动后,Android Volley不会从服务器加载数据

时间:2015-04-15 11:02:14

标签: android android-activity android-volley

我有一个很大的问题就是现在困扰我几天。在我正在开发的应用程序中,我有几个活动,其中一个是中心(BaseActivity),应用程序从中进入其他活动,并且每个活动都与Volley Library一起从API获取数据。

因此,例如,如果我从BaseActivity转到SelectionActivity,则在SelectionActivity中,我会收到包含所有必要数据的循环视图。这很好,这就是我需要的。

但是,当我通过单击工具栏上的后退按钮或主页按钮完成活动,然后想要再次返回到SelectionActivity时,数据不会再次加载。它没有说明任何异常,只是没有加载任何东西。

我一直在互联网上搜索,但我似乎无法找到解决方案。

编辑:当我使用调试器进行调查时,可以进一步确定。似乎一切都应该有效,因为它通过响应,并通过一切。但是,我没有看到任何内容,而是使用了填充数据的RecyclerView。

SelectionController方法:

public void getAllJobs()
{
    queue = VolleyRequestHandler.getInstance(false).getQueue();

    JsonArrayRequest jobsRequest = new JsonArrayRequest(Request.Method.GET,makeAllJobsRequest(),
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    List<Job> jobs = new ArrayList<>();
                    Job job;
                    try
                    {
                        for (int i=0; i<response.length(); i++)
                        {
                            JSONObject dbJob = response.getJSONObject(i);
                            job = new Job();

                            job.setId(dbJob.getLong("JobId"));
                            job.setName(dbJob.getString("JobText"));
                            job.setCustName(dbJob.getString("CustomerName"));

                            jobs.add(job);
                        }

                        // Entries are being sorted!
                        Collections.sort(jobs, new CustomerComparator());

                        injection.onGettingAllJobs(jobs);
                    }
                    catch (JSONException e)
                    {
                        e.printStackTrace();
                        injection.onErrorSelection(e.getMessage());
                    }
                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            injection.onErrorSelection(error.getMessage());
        }
    });

    jobsRequest.setTag(injection.GET_JOBS_TAG);

    jobsRequest.setRetryPolicy(new DefaultRetryPolicy(
            (int) TimeUnit.SECONDS.toMillis(10),//time out in 10second
            DefaultRetryPolicy.DEFAULT_MAX_RETRIES,//DEFAULT_MAX_RETRIES = 1;
            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

    queue.add(jobsRequest);
}

SelectionInjection接口:

public interface SelectionInjection
{
    public static final String GET_JOBS_TAG = "SELECTION_GET_JOBS_TAG";
    public static final String GET_TASKS_TAG = "SELECTION_GET_TASKS_TAG";
    public static final String SAVE_ENTRY_TAG ="SELECTION_SAVE_ENTRY_TAG";

    public void onGettingAllJobs(List<Job> jobs);

    public void onGettingTasksForJob(List<Task> tasks);

    public void onSavedEntry(TimeEntry savedEntry);

    public void onErrorSelection(String message);
}

SelectionActivity:

public class SelectionActivity extends ActionBarActivity implements SelectionInjection {

    private static final String TAG = SelectionActivity.class.getName();

    /*
    * Init variables for Recycler Views
    * */
    private LinearLayoutManager mLayoutManager;
    private SelectJobAdapter mJobsAdapter;
    private StickyHeadersItemDecoration headers;
    private SelectTaskAdapter mSelectTaskAdapter;

    /*
    * Lists used for adapter and for storing information from server
    * */
    private List<Job> mJobs;
    private List<Task> mTasks;
    private SelectionController controller;
    private Job selectedJob;


    // Inject Views with ButterKnife
    @InjectView(R.id.select_job_recyclerview) SuperRecyclerView mJobSuperRecyclerView;
    @InjectView(R.id.select_task_recyclerview) SuperRecyclerView mTaskSuperRecyclerView;
    @InjectView(R.id.job_view)FrameLayout mJobView;
    @InjectView(R.id.task_view) FrameLayout mTaskView;
    @InjectView(R.id.toolbar_actionbar) Toolbar mToolbarAction;

    private int mAnimDuration;
//    private SelectionTask mFetchingTask; // Is it a good idea to Init it here? -> Nej
//    private SaveSelectionTask mSavingTask;


    // TODO: Figure out why after coming back again to this activity, there is only a loading wheel and nothing shows up
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_selection);
        ButterKnife.inject(this);

        /*
        *  Setting up stuff for ViewSwitching
        * */
        mTaskView.setVisibility(View.GONE); // Also set in XMl but just in case :D
        mAnimDuration = getResources()
                .getInteger(android.R.integer.config_mediumAnimTime);
        /*
        * Setting Up Action Bar
        * */
        mToolbarAction.setTitle(getString(R.string.select_job_title));
        setSupportActionBar(mToolbarAction);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true); // Hierarchical activity

        if (mJobs == null) {
            // provifing dummy test data
            Log.v(TAG, "mJobs are are null");
//            mJobs = new ArrayList<Job>();
//            List<Task> taskList = new ArrayList<Task>();
//            taskList.add(
//                    new Task(88,"Task Name Doh")
//                    );
//            taskList.add(
//                    new Task(99,"Another Task Name Doh")
//            );
//            mJobs.add(
//                    new Job(
//                            10,
//                            "Test Job",
//                            1337,
//                            "Fake Customer",
//                            taskList
//                            ));
            fetchJobs();
        }
        else
        {
            setUpJobRecyclerView();
        }
    }



    private void fetchJobs() {
        Log.v(TAG,"fetchJobs();");
//        mFetchingTask = new SelectionTask();
//        mFetchingTask.execute(); // No PAram, get all the jobs
        controller = SelectionController.getInstance(BaseActivity.currentUser,this);
        controller.getAllJobs();
    }

    private void fetchTasks(Job job){
        Log.v(TAG,"fetchTAsks()");
        try{
//            mFetchingTask = new SelectionTask();
//            mFetchingTask.execute(job);

            controller = SelectionController.getInstance(BaseActivity.currentUser,this);
            controller.getTasksForJob(job);

        }catch (Exception e){
            Log.v(TAG,"There was an error fetching tasks");
            e.printStackTrace();
            Toast.makeText(this,"There was error fetching tasks",Toast.LENGTH_LONG).show();
        }
    }


    /**
     * Method for setting up Job Recycler View
     */
    private void setUpJobRecyclerView(){
        /*
        * Setting up Jobs Recycler View
        * */
        mJobsAdapter = new SelectJobAdapter(mJobs);
        mJobsAdapter.setHasStableIds(true);
        headers = new StickyHeadersBuilder()
                .setAdapter(mJobsAdapter)
                .setRecyclerView(mJobSuperRecyclerView.getRecyclerView())
                .setStickyHeadersAdapter(new SelectJobHeaderAdapter(mJobs))
                .build();

        mJobSuperRecyclerView.setAdapter(mJobsAdapter);
        mJobSuperRecyclerView.addItemDecoration(headers);

        mLayoutManager = new LinearLayoutManager(this);
        mJobSuperRecyclerView.setLayoutManager(mLayoutManager);
        // Setting up onClickListener
        mJobSuperRecyclerView.
                addOnItemTouchListener(
                        new RecyclerUtils.RecyclerItemClickListener(
                                this,
                                new RecyclerUtils.RecyclerItemClickListener.OnItemClickListener() {
                                    @Override
                                    public void onItemClick(View view, int position) {
                                        selectedJob = mJobs.get(position);
                                        showMaterialDialog(position);
                                    }
                                }));
    }
    /**
    * Method used for settigng up and initalising all the adapters
     * for TaskRecyclerView
    * */
    private void setUpTaskRecyclerView() {
        mLayoutManager = new LinearLayoutManager(this);
        mTaskSuperRecyclerView.setLayoutManager(mLayoutManager);
        mSelectTaskAdapter = new SelectTaskAdapter(mTasks);
        mSelectTaskAdapter.setHasStableIds(true);
        headers = new StickyHeadersBuilder()
                .setAdapter(mSelectTaskAdapter)
                .setRecyclerView(mTaskSuperRecyclerView.getRecyclerView())
                .setStickyHeadersAdapter(new SelectTaskHeaderAdapter(mTasks))
                .build();

        mTaskSuperRecyclerView.setAdapter(mSelectTaskAdapter);
        mTaskSuperRecyclerView.addItemDecoration(headers);
        mTaskSuperRecyclerView.
                addOnItemTouchListener(
                        new RecyclerUtils.RecyclerItemClickListener(
                                this,
                                new RecyclerUtils.RecyclerItemClickListener.OnItemClickListener() {
                                    @Override
                                    public void onItemClick(View view, int position) {
                                        Log.v(TAG,"TaskRecyclerView onItemClick");
                                        Toast.makeText(getApplicationContext(),"The Task has been added",Toast.LENGTH_LONG).show();
//                                        mSavingTask = new SaveSelectionTask();
//                                        mSavingTask.execute(mTasks.get(position));
                                    }
                                }));

    }

    /**
     * A method that starts a corssfade Animation between JobView and TaskView
     *
     */
    private void crossfadeViews(final View fromView, View toView){
        // Set the Task view to 0% opacity but visible, so that it is visible
        // (but fully transparent) during the animation.
        toView.setAlpha(0f);
        toView.setVisibility(View.VISIBLE);

        // Animate the Task view to 100% opacity, and clear any animation
        // listener set on the view.
        toView.animate()
                .alpha(1f)
                .setDuration(mAnimDuration)
                .setListener(null);

        // Animate the Job view to 0% opacity. After the animation ends,
        // set its visibility to GONE as an optimization step (it won't
        // participate in layout passes, etc.)
        fromView.animate()
                .alpha(0f)
                .setDuration(mAnimDuration)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        fromView.setVisibility(View.GONE);
                    }
                });
    }

    /**
     * Method that creates and shows a Dialog
     * and executes fetchTasks() if given option is picked.
     */
    private void showMaterialDialog(final int position){
        // TODO: Consider starting running he Async Task straight away as
        //       it might be likely that the user will pick "Pcik A Task" option
        //       and this might speed up the process
        Log.v(TAG,"showMAterialDialog");
        new MaterialDialog.Builder(this)
                .title("Choose Action")
                .positiveText("Add Job")
                .negativeText("Pick A Task")
                .neutralText("CANCEL")
                .callback(new MaterialDialog.ButtonCallback(){
                    @Override
                    public void onPositive(MaterialDialog dialog) {
                        // Add Job
                        Log.v(TAG,"Adding the whole Job");
//                        mSavingTask = new SaveSelectionTask();
//                        mSavingTask.execute();
                        controller = SelectionController.getInstance(BaseActivity.currentUser,SelectionActivity.this);
                        controller.saveNewTimeEntry(BaseActivity.selectedDate,selectedJob,null);
                    }

                    @Override
                    public void onNegative(MaterialDialog dialog) {
                        /**
                         *Pick a Task
                         */
                        fetchTasks(mJobs.get(position));
                        Log.v(TAG, "Switching Views");
                        crossfadeViews(mJobView, mTaskView);
                    }

                    @Override
                    public void onNeutral(MaterialDialog dialog) {
                        Log.v(TAG,"Cancelling the Dialog Choice");

                    }
                }).show();

    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.global, 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();

        try
        {
            switch(id)
            {
                case R.id.action_settings:

                    return true;
                case android.R.id.home:
                    if (mTaskView.getVisibility() == View.VISIBLE)
                    {
                        crossfadeViews(mTaskView,mJobView);
                    }
                    else
                    {
                        finish();
                    }
                    return true;
                default:
                    throw new Exception();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onSavedEntry(TimeEntry savedEntry)
    {
        Log.v("SAVED ENTRY", "TRUE");
        System.out.println(savedEntry.toString());
        controller.closeQueue(SAVE_ENTRY_TAG);
    }

    @Override
    public void onGettingAllJobs(List<Job> jobs) {
        mJobs = jobs;
        setUpJobRecyclerView();
        controller.closeQueue(GET_JOBS_TAG);
    }

    @Override
    public void onGettingTasksForJob(List<Task> tasks) {
        mTasks = tasks;
        setUpTaskRecyclerView();
        controller.closeQueue(GET_TASKS_TAG);
    }

    @Override
    public void onErrorSelection(String message) {
        Log.v(TAG,"onErrorJobTask");
    }
}

1 个答案:

答案 0 :(得分:2)

经过大量调试后,我遇到了解决方案:

似乎我制作控制器和注入的方式并不适合Android开发,因此我已将代码重新组织回活动和片段,现在所有工作都已完成。

编辑:

最后我弄清楚了实际问题是什么。当我将Context传递给Controller时...我只在实际实例化它时才这样做。而且因为在我的情况下控制器是单例,所以在重新进入Activity时我一直在使用旧的上下文。

我无法相信我没有得到那个。 :)