来自本地数据存储的Android Parse查询速度太慢

时间:2015-07-02 22:22:35

标签: java android parse-platform saving-data

在我的主要活动中,我用一系列字符串填充Recyclerview;但是,我从我的解析数据库中获取这些字符串。

我现在知道,当您查询信息时,该方法是异步的,这意味着它在后台运行,等待您的代码继续运行时从数据库接收响应。我遇到的问题是,用字符串填充数组花了太长时间并且recycerview已经填充了(因为数组还没有被填充,所以使用空值)

所以我决定使用parse在本地保存数据并使用数据库来备份信息。我的问题仍然是,这也太慢了,无法填充我的适配器以进行recyclerview。我甚至确保它不会查询数据库,并将我的数据和互联网连接转换为我正在测试它的手机。这是同一个故事。

有没有人知道检索数据的优化方法,因此它足够快以填充回收者视图,因为现在需要整整3秒钟来获取字符串。我不想暂停我的程序3秒钟只是为了等待解析它做的事情。

以下是我保存数据的方法。

// get current user
ParseObject studentClasses = new ParseObject("StudentClasses");

// register their periods into database
studentClasses.put("student_id", ParseUser.getCurrentUser());
studentClasses.put("first_period", ClassSelected_Period[PERIOD1]);
studentClasses.put("second_period", ClassSelected_Period[PERIOD2]);
studentClasses.put("third_period", ClassSelected_Period[PERIOD3]);
studentClasses.put("fourth_period", ClassSelected_Period[PERIOD4]);
studentClasses.put("fifth_period", ClassSelected_Period[PERIOD5]);
studentClasses.put("sixth_period", ClassSelected_Period[PERIOD6]);
studentClasses.put("seventh_period", ClassSelected_Period[PERIOD7]);

// save the information locally and in database
studentClasses.pinInBackground();

// navigate user home
navigateToHome();

以下是我在主要活动中检索数据的方法

// query database for user's classes
ParseQuery<ParseObject> query = ParseQuery.getQuery("StudentClasses");
query.fromLocalDatastore().whereEqualTo("student_id", ParseUser.getCurrentUser());

// find it, first looking at local data store then going to database
query.getFirstInBackground(new GetCallback<ParseObject>()
{
    @Override
    public void done (ParseObject parseObject, ParseException e)
    {
        if (e == null)
        {
            // retrieved the object
            userClasses[PERIOD1] = parseObject.getString("first_period");
            userClasses[PERIOD2] = parseObject.getString("second_period");
            userClasses[PERIOD3] = parseObject.getString("third_period");
            userClasses[PERIOD4] = parseObject.getString("fourth_period");
            userClasses[PERIOD5] = parseObject.getString("fifth_period");
            userClasses[PERIOD6] = parseObject.getString("sixth_period");
            userClasses[PERIOD7] = parseObject.getString("seventh_period");

            // DEBUG: shows how long it takes for method to return
            Toast.makeText(getApplicationContext(),"during call = " + userClasses[PERIOD1], Toast.LENGTH_LONG).show();
        }
        else
        {
            // DEBUG: shows if exception happened
            Toast.makeText(getApplicationContext(),"Exception Thrown" ,Toast.LENGTH_SHORT).show();
        }
    }
});

// DEBUG: shows how long it takes for code to reach this point
Toast.makeText(getApplicationContext(),"after call = " + userClasses[PERIOD1], Toast.LENGTH_LONG).show();

吐司&#34;跟电话=&#34;屏幕出现后几乎显示,并且在调用= null&#34;之后显示&#34;

toast&#34;在通话期间=&#34;大约3秒钟后出现并在通话期间说#34;英语&#34; (这应该是什么意思)

即使它没有使用解析来保存它,我也会没事的。我总是可以使用解析来支持它,或者我只是做错了什么,并且有更好的方法。

如果您有兴趣,这是我的整个主要活动

    package maxbleggi.afstudentplanner;

import ... 

public class MainActivity extends AppCompatActivity
{
    // "MACROS" for user's class periods
    private final int PERIOD1 = 0;
    private final int PERIOD2 = 1;
    private final int PERIOD3 = 2;
    private final int PERIOD4 = 3;
    private final int PERIOD5 = 4;
    private final int PERIOD6 = 5;
    private final int PERIOD7 = 6;

    // toolbar
    private Toolbar toolbar;

    // navigation drawer
    private DrawerLayout navDrawer;

    // user's data
     public String[] userClasses = new String[10];

    // list to fill Classroom class with
    private List<ClassroomClass> classrooms;

    /*
    * on creation of activity
     */
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // initialise and set toolbar as actionbar
        toolbar = (Toolbar) findViewById(R.id.tool_bar);
        setSupportActionBar(toolbar);

        // initialize nav bars
        initNavBars();

        // initialize drawer layout
        NavigationView navView = (NavigationView) findViewById(R.id.navigation_view);

        // initialize nav drawer
        navDrawer = (DrawerLayout) findViewById(R.id.drawer);
        initNavDrawer(navDrawer);

        // initialize layout manager for recycler view
        RecyclerView.LayoutManager mainLayoutManager = new LinearLayoutManager(this);

        // initialize data for all classes before setting adapter
        initClassData();

        // set the adapter for recycler view
        RecyclerView.Adapter mainAdapter = new MainRecyclerAdapter(classrooms);

        // initialize recycler view elements
        RecyclerView mainRecyclerView = (RecyclerView) findViewById(R.id.main_recycler_view);

        // add layout manager to recycler view
        mainRecyclerView.setLayoutManager(mainLayoutManager);

        // add adapter to recycler view
        mainRecyclerView.setAdapter(mainAdapter);
    }

    /*
    * initializes the class data for each class
    */
    public void initClassData()
    {
        // check if a user is not cached
        ParseUser currentUser = ParseUser.getCurrentUser();
        if (currentUser == null)
        {
            // prompt user to Register screen
            // create intent to start activity
            Intent intent = new Intent(MainActivity.this, RegisterActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

            // start new activity
            startActivity(intent);

            // stop current activity
            finish();
        }

        // query database for user's classes
        ParseQuery<ParseObject> query = ParseQuery.getQuery("StudentClasses");
        query.fromLocalDatastore().whereEqualTo("student_id", ParseUser.getCurrentUser());

        // find it, first looking at local data store then going to database
        query.getFirstInBackground(new GetCallback<ParseObject>()
        {
            @Override
            public void done (ParseObject parseObject, ParseException e)
            {
                if (e == null)
                {
                    // retrieved the object
                    userClasses[PERIOD1] = parseObject.getString("first_period");
                    userClasses[PERIOD2] = parseObject.getString("second_period");
                    userClasses[PERIOD3] = parseObject.getString("third_period");
                    userClasses[PERIOD4] = parseObject.getString("fourth_period");
                    userClasses[PERIOD5] = parseObject.getString("fifth_period");
                    userClasses[PERIOD6] = parseObject.getString("sixth_period");
                    userClasses[PERIOD7] = parseObject.getString("seventh_period");

                    // DEBUG: shows how long it takes for method to return
                    Toast.makeText(getApplicationContext(),"during call = " + userClasses[PERIOD1], Toast.LENGTH_LONG).show();
                }
                else
                {
                    // DEBUG: shows if exception happened
                    Toast.makeText(getApplicationContext(),"Exception Thrown" ,Toast.LENGTH_SHORT).show();
                }
            }
        });

        // DEBUG: shows how long it takes for code to reach this point
        Toast.makeText(getApplicationContext(),"after call = " + userClasses[PERIOD1], Toast.LENGTH_LONG).show();

        // fill all fields for class periods
        classrooms = new ArrayList<>();

        // titles of classes to add to list
        String[] classTitles = {"First Period", "Second Period", "Third Period", "Fourth Period",
                "Fifth Period", "Sixth Period", "Seventh Period"};

            // iterate over every period to add it to the list
            for (int i = 0; i <= PERIOD7; i++)
            {
                // if there was a class registered for that period
                if (userClasses[PERIOD3] != null)
                {
                    // add it to the class to be added to recycler view
                    classrooms.add(new ClassroomClass(userClasses[i], classTitles[i], i + 1));
                }
            }

    }

    /*
    * initialize navigation drawer
     */
    public void initNavDrawer(final DrawerLayout navDrawer)
    {
        final NavigationView navView = (NavigationView) findViewById(R.id.navigation_view);

        navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener()
        {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem)
            {
                menuItem.setChecked(true);
                navDrawer.closeDrawers();
                return true;
            }
        });
    }

    /*
    * initialize navigation bars to allow navigation to nav drawer
    */
    private void initNavBars()
    {
       if (toolbar != null)
       {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            toolbar.setNavigationIcon(R.drawable.ic_menu_white);
            toolbar.setNavigationOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    navDrawer.openDrawer(GravityCompat.START);
                }
            });
       }
    }
}

感谢任何部分的任何优化或修复!

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。它可能不是最优雅或最有效的,但至少它是有效的。

不使用parse作为保存数据的主要来源,而是将其用作备份来检查内部存储的数据。因此,使用parse正常保存数据,然后使用共享首选项保存数据类型,这将在内部保存数据。 就我而言,它看起来像这样

PreferenceManager.getDefaultSharedPreferences(RegisterActivity.this).edit().putString("my_title", myCustomString).commit();

如果RegisterActivity.this是您的上下文,my_title是您的字符串的唯一ID,myCustomString是您要保存的自定义字符串

您所要做的就是使用那一行来保存您想要的变量。

当您想要检索数据时,只需将此行

myNewString = PreferenceManager.getDefaultSharedPreferences(MainActivity.this).getString("my_title", "defaultStringIfNothingFound");

myNewString是你保存的新字符串,MainActivity.this是上下文,my_title仍然是标题,而defaultString ......很明显。

您仍然可以维护数据库检查。只需将保存共享首选项行设置为等于parseObject.getString("StringName");等于

的任何内容

现在您有一个用于保存和检索数据的快速本地缓存和一个用于定期更新本地缓存的冗余数据库